From ad908a746163e265b18f11ad9181bf4c2cb062fd Mon Sep 17 00:00:00 2001 From: andatoshiki Date: Fri, 3 Nov 2023 22:54:31 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20andatosh?= =?UTF-8?q?iki/toshiki-notebook@7c2f41331b6db88cc056dfc52d6a1549ef3b312d?= =?UTF-8?q?=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 404.html | 8 +- academic/chemistry/index.html | 12 +- academic/chemistry/notes/12-5.html | 12 +- academic/chemistry/problems/02-20.html | 12 +- academic/chemistry/problems/03-02-1.html | 12 +- academic/chemistry/problems/03-02-2.html | 12 +- academic/chemistry/problems/03-02-3.html | 12 +- academic/literature/index.html | 12 +- .../writing/methods-of-development.html | 12 +- academic/physics/index.html | 12 +- academic/physics/ipho-formulas-jpn/1.html | 14 +- academic/physics/ipho-formulas-jpn/10.html | 14 +- academic/physics/ipho-formulas-jpn/11.html | 14 +- academic/physics/ipho-formulas-jpn/12.html | 12 +- academic/physics/ipho-formulas-jpn/13.html | 14 +- academic/physics/ipho-formulas-jpn/2.html | 12 +- academic/physics/ipho-formulas-jpn/3.html | 12 +- academic/physics/ipho-formulas-jpn/4.html | 14 +- academic/physics/ipho-formulas-jpn/5.html | 14 +- academic/physics/ipho-formulas-jpn/6.html | 12 +- academic/physics/ipho-formulas-jpn/7.html | 14 +- academic/physics/ipho-formulas-jpn/8.html | 14 +- academic/physics/ipho-formulas-jpn/9.html | 12 +- academic/vocabulary/2023/02/2023-02-27.html | 12 +- academic/vocabulary/index.html | 12 +- application/markdown-it-katex/how-to-use.html | 74 +- .../markdown-it-katex/support-function.html | 14 +- .../markdown-it-katex/support-table.html | 14 +- application/markdown-it-katex/tips.html | 172 +- .../api/annotations.html | 120 +- .../api/cutting.html | 96 +- .../api/emit.html | 88 +- .../api/errors.html | 44 +- .../api/includes.html | 196 +- .../api/logging.html | 42 +- .../api/multi-file.html | 156 +- .../api/queries.html | 44 +- .../api/types.html | 96 +- .../config/flags.html | 1192 +- .../config/reference.html | 176 +- .../guide/custom-theme.html | 160 +- .../guide/markdown-extensions.html | 24 +- .../index.html | 144 +- assets/2023-11-02-04-44-14.08b67c2b.png | Bin 0 -> 346782 bytes assets/2023-11-04-00-42-58.d7bf77fb.png | Bin 0 -> 505971 bytes assets/2023-11-04-01-32-28.da2149a9.png | Bin 0 -> 365642 bytes assets/2023-11-04-03-15-12.77ab4cd9.png | Bin 0 -> 167926 bytes assets/2023-11-04-03-49-38.78c93d29.png | Bin 0 -> 179688 bytes assets/2023-11-04-04-27-59.3d817820.png | Bin 0 -> 231697 bytes assets/2023-11-04-05-01-04.fd5f8fb7.png | Bin 0 -> 139482 bytes ...> academic_chemistry_index.md.56f381d7.js} | 2 +- ...demic_chemistry_index.md.56f381d7.lean.js} | 2 +- ...demic_chemistry_notes_12-5.md.f9fc6ef4.js} | 2 +- ..._chemistry_notes_12-5.md.f9fc6ef4.lean.js} | 2 +- ...c_chemistry_problems_02-20.md.86be96e0.js} | 2 +- ...mistry_problems_02-20.md.86be96e0.lean.js} | 2 +- ...chemistry_problems_03-02-1.md.a9ee56be.js} | 2 +- ...stry_problems_03-02-1.md.a9ee56be.lean.js} | 2 +- ...chemistry_problems_03-02-2.md.a4b8c746.js} | 2 +- ...stry_problems_03-02-2.md.a4b8c746.lean.js} | 2 +- ...chemistry_problems_03-02-3.md.152b3eb2.js} | 2 +- ...stry_problems_03-02-3.md.152b3eb2.lean.js} | 2 +- ... academic_literature_index.md.bd51fa1c.js} | 2 +- ...emic_literature_index.md.bd51fa1c.lean.js} | 2 +- ...ing_methods-of-development.md.bcfb091e.js} | 2 +- ...ethods-of-development.md.bcfb091e.lean.js} | 2 +- ... => academic_physics_index.md.6ec0ff5a.js} | 2 +- ...cademic_physics_index.md.6ec0ff5a.lean.js} | 2 +- ...hysics_ipho-formulas-jpn_1.md.b1c8984c.js} | 2 +- ...s_ipho-formulas-jpn_1.md.b1c8984c.lean.js} | 2 +- ...ysics_ipho-formulas-jpn_10.md.2eaa8ad2.js} | 2 +- ..._ipho-formulas-jpn_10.md.2eaa8ad2.lean.js} | 2 +- ...ysics_ipho-formulas-jpn_11.md.3b777f56.js} | 2 +- ..._ipho-formulas-jpn_11.md.3b777f56.lean.js} | 2 +- ...ysics_ipho-formulas-jpn_12.md.449de813.js} | 2 +- ..._ipho-formulas-jpn_12.md.449de813.lean.js} | 2 +- ...ysics_ipho-formulas-jpn_13.md.20d2560f.js} | 2 +- ..._ipho-formulas-jpn_13.md.20d2560f.lean.js} | 2 +- ...hysics_ipho-formulas-jpn_2.md.6d273404.js} | 2 +- ...s_ipho-formulas-jpn_2.md.6d273404.lean.js} | 2 +- ...hysics_ipho-formulas-jpn_3.md.6485844d.js} | 2 +- ...s_ipho-formulas-jpn_3.md.6485844d.lean.js} | 2 +- ...hysics_ipho-formulas-jpn_4.md.47f0821f.js} | 2 +- ...s_ipho-formulas-jpn_4.md.47f0821f.lean.js} | 2 +- ...hysics_ipho-formulas-jpn_5.md.948cb5df.js} | 2 +- ...s_ipho-formulas-jpn_5.md.948cb5df.lean.js} | 2 +- ...hysics_ipho-formulas-jpn_6.md.d563d3f1.js} | 2 +- ...s_ipho-formulas-jpn_6.md.d563d3f1.lean.js} | 2 +- ...hysics_ipho-formulas-jpn_7.md.b0bd68dd.js} | 2 +- ...s_ipho-formulas-jpn_7.md.b0bd68dd.lean.js} | 2 +- ...hysics_ipho-formulas-jpn_8.md.f05c02fb.js} | 2 +- ...s_ipho-formulas-jpn_8.md.f05c02fb.lean.js} | 2 +- ...hysics_ipho-formulas-jpn_9.md.083302ab.js} | 2 +- ...s_ipho-formulas-jpn_9.md.083302ab.lean.js} | 2 +- ...abulary_2023_02_2023-02-27.md.3ec19aaf.js} | 2 +- ...ry_2023_02_2023-02-27.md.3ec19aaf.lean.js} | 2 +- ... academic_vocabulary_index.md.37eb0530.js} | 2 +- ...emic_vocabulary_index.md.37eb0530.lean.js} | 2 +- assets/{app.6020b1dd.js => app.11c168a7.js} | 2 +- ...arkdown-it-katex_how-to-use.md.b10dd06e.js | 50 + ...n-it-katex_how-to-use.md.b10dd06e.lean.js} | 4 +- ...arkdown-it-katex_how-to-use.md.e6ab0018.js | 50 - ...-it-katex_support-function.md.59634b4a.js} | 2 +- ...atex_support-function.md.59634b4a.lean.js} | 2 +- ...own-it-katex_support-table.md.419e3a5e.js} | 2 +- ...t-katex_support-table.md.419e3a5e.lean.js} | 2 +- ...tion_markdown-it-katex_tips.md.4fa4c33c.js | 97 - ...tion_markdown-it-katex_tips.md.d87fb855.js | 97 + ...arkdown-it-katex_tips.md.d87fb855.lean.js} | 2 +- ...ki-twoslash_api_annotations.md.105e6b7f.js | 94 - ...oslash_api_annotations.md.105e6b7f.lean.js | 40 - ...ki-twoslash_api_annotations.md.a42ad2a7.js | 94 + ...oslash_api_annotations.md.a42ad2a7.lean.js | 40 + ...-shiki-twoslash_api_cutting.md.2a5fd9c3.js | 45 + ...i-twoslash_api_cutting.md.2a5fd9c3.lean.js | 45 + ...-shiki-twoslash_api_cutting.md.b6b7a28c.js | 45 - ...i-twoslash_api_cutting.md.b6b7a28c.lean.js | 45 - ...gin-shiki-twoslash_api_emit.md.07068d46.js | 1 + ...iki-twoslash_api_emit.md.07068d46.lean.js} | 2 +- ...gin-shiki-twoslash_api_emit.md.8d757f81.js | 1 - ...n-shiki-twoslash_api_errors.md.230e0002.js | 9 + ...ki-twoslash_api_errors.md.230e0002.lean.js | 9 + ...n-shiki-twoslash_api_errors.md.8032d46f.js | 9 - ...ki-twoslash_api_errors.md.8032d46f.lean.js | 9 - ...shiki-twoslash_api_includes.md.b534e723.js | 99 + ...-twoslash_api_includes.md.b534e723.lean.js | 99 + ...shiki-twoslash_api_includes.md.d69b2a67.js | 99 - ...-twoslash_api_includes.md.d69b2a67.lean.js | 99 - ...-shiki-twoslash_api_logging.md.8b741477.js | 20 + ...i-twoslash_api_logging.md.8b741477.lean.js | 20 + ...-shiki-twoslash_api_logging.md.d3641bab.js | 20 - ...i-twoslash_api_logging.md.d3641bab.lean.js | 20 - ...iki-twoslash_api_multi-file.md.48f61f4c.js | 71 + ...woslash_api_multi-file.md.48f61f4c.lean.js | 71 + ...iki-twoslash_api_multi-file.md.aea0802f.js | 71 - ...woslash_api_multi-file.md.aea0802f.lean.js | 71 - ...-shiki-twoslash_api_queries.md.8c3dbc97.js | 17 + ...i-twoslash_api_queries.md.8c3dbc97.lean.js | 17 + ...-shiki-twoslash_api_queries.md.9bd11a96.js | 17 - ...i-twoslash_api_queries.md.9bd11a96.lean.js | 17 - ...in-shiki-twoslash_api_types.md.9dbcbe1c.js | 45 - ...iki-twoslash_api_types.md.9dbcbe1c.lean.js | 45 - ...in-shiki-twoslash_api_types.md.a1a99084.js | 45 + ...iki-twoslash_api_types.md.a1a99084.lean.js | 45 + ...shiki-twoslash_config_flags.md.52b87b95.js | 591 + ...-twoslash_config_flags.md.52b87b95.lean.js | 1 + ...shiki-twoslash_config_flags.md.a683705b.js | 591 - ...-twoslash_config_flags.md.a683705b.lean.js | 1 - ...i-twoslash_config_reference.md.42f9e642.js | 83 - ...slash_config_reference.md.42f9e642.lean.js | 11 - ...i-twoslash_config_reference.md.e7b86a5d.js | 83 + ...slash_config_reference.md.e7b86a5d.lean.js | 11 + ...twoslash_guide_custom-theme.md.287ab776.js | 85 + ...ash_guide_custom-theme.md.287ab776.lean.js | 3 + ...twoslash_guide_custom-theme.md.58ed95fc.js | 85 - ...ash_guide_custom-theme.md.58ed95fc.lean.js | 3 - ...h_guide_markdown-extensions.md.6731e737.js | 7 - ...de_markdown-extensions.md.6731e737.lean.js | 7 - ...h_guide_markdown-extensions.md.a9cd6c63.js | 7 + ...de_markdown-extensions.md.a9cd6c63.lean.js | 7 + ...plugin-shiki-twoslash_index.md.7fc07d32.js | 111 - ...n-shiki-twoslash_index.md.7fc07d32.lean.js | 71 - ...plugin-shiki-twoslash_index.md.e8d8a5ec.js | 111 + ...n-shiki-twoslash_index.md.e8d8a5ec.lean.js | 71 + ...242a.js => VPAlgoliaSearchBox.c32b1d6a.js} | 2 +- .../{theme.7de1b093.js => theme.c3ca1c74.js} | 2 +- ...opment_aws_acknowledgement.md.ebd64504.js} | 2 +- ...t_aws_acknowledgement.md.ebd64504.lean.js} | 2 +- .../development_aws_appendix.md.071021e4.js | 29 + ...velopment_aws_appendix.md.071021e4.lean.js | 1 + .../development_aws_appendix.md.568c3e80.js | 29 - ...velopment_aws_appendix.md.568c3e80.lean.js | 1 - ...evelopment_aws_assignments.md.fcb27d2d.js} | 2 +- ...pment_aws_assignments.md.fcb27d2d.lean.js} | 2 +- ... => development_aws_author.md.a292956b.js} | 2 +- ...evelopment_aws_author.md.a292956b.lean.js} | 2 +- .../development_aws_aws-batch.md.76d54c51.js | 456 + ...elopment_aws_aws-batch.md.76d54c51.lean.js | 1 + .../development_aws_aws-batch.md.de2d649a.js | 456 - ...elopment_aws_aws-batch.md.de2d649a.lean.js | 1 - ...lopment_aws_aws-get-started.md.5e1dfdb2.js | 149 + ...nt_aws_aws-get-started.md.5e1dfdb2.lean.js | 1 + ...lopment_aws_aws-get-started.md.e1a56953.js | 149 - ...nt_aws_aws-get-started.md.e1a56953.lean.js | 1 - ...=> development_aws_closing.md.0cdd4f54.js} | 2 +- ...velopment_aws_closing.md.0cdd4f54.lean.js} | 2 +- ...s => development_aws_cloud.md.148d68f2.js} | 2 +- ...development_aws_cloud.md.148d68f2.lean.js} | 2 +- ...ment_aws_docker-system.md.4275fd21.lean.js | 1 - ...elopment_aws_docker-system.md.dcee24fc.js} | 106 +- ...ment_aws_docker-system.md.dcee24fc.lean.js | 1 + ...ment_aws_handson-bashoutter.md.890a8ec8.js | 409 + ...ws_handson-bashoutter.md.890a8ec8.lean.js} | 2 +- ...ment_aws_handson-bashoutter.md.d59bc53b.js | 409 - ...development_aws_handson-ec2.md.2a763e5b.js | 193 - ...development_aws_handson-ec2.md.43188290.js | 193 + ...pment_aws_handson-ec2.md.43188290.lean.js} | 2 +- ...lopment_aws_handson-jupyter.md.7f479319.js | 247 - ...nt_aws_handson-jupyter.md.7f479319.lean.js | 1 - ...lopment_aws_handson-jupyter.md.e87bcd1f.js | 247 + ...nt_aws_handson-jupyter.md.e87bcd1f.lean.js | 1 + ...velopment_aws_handson-qabot.md.27ff1082.js | 172 + ...ment_aws_handson-qabot.md.27ff1082.lean.js | 1 + ...velopment_aws_handson-qabot.md.3c125433.js | 172 - ...ment_aws_handson-qabot.md.3c125433.lean.js | 1 - ...ment_aws_handson-serverless.md.330af1e8.js | 219 - ...aws_handson-serverless.md.330af1e8.lean.js | 1 - ...ment_aws_handson-serverless.md.7fbfa1f9.js | 219 + ...aws_handson-serverless.md.7fbfa1f9.lean.js | 1 + ...s => development_aws_index.md.0fcf5beb.js} | 2 +- ...development_aws_index.md.0fcf5beb.lean.js} | 2 +- ...=> development_aws_license.md.38e84b81.js} | 2 +- ...velopment_aws_license.md.38e84b81.lean.js} | 2 +- assets/development_aws_main.md.587d14dd.js | 1911 ++ .../development_aws_main.md.587d14dd.lean.js | 1 + assets/development_aws_main.md.58c079df.js | 1911 -- .../development_aws_main.md.58c079df.lean.js | 1 - ...t_aws_scientific-computing.md.194874e2.js} | 2 +- ..._scientific-computing.md.194874e2.lean.js} | 2 +- ...development_aws_serverless.md.a89d6134.js} | 2 +- ...opment_aws_serverless.md.a89d6134.lean.js} | 2 +- ... development_aws_webserver.md.89157904.js} | 2 +- ...lopment_aws_webserver.md.89157904.lean.js} | 2 +- ...ent_file-naming-convention.md.0fb858f4.js} | 134 +- ...ile-naming-convention.md.0fb858f4.lean.js} | 2 +- ...opment_proxy4shell-terminal.md.a93dc7e4.js | 79 + ...t_proxy4shell-terminal.md.a93dc7e4.lean.js | 1 + .../development_rclone-for-r2.md.65c0da34.js | 55 + ...elopment_rclone-for-r2.md.65c0da34.lean.js | 1 + .../development_rclone-for-r2.md.72ca2dcc.js | 55 - ...elopment_rclone-for-r2.md.72ca2dcc.lean.js | 1 - assets/getting-started.md.54a05997.js | 11 - assets/getting-started.md.975024a7.js | 11 + ...js => getting-started.md.975024a7.lean.js} | 2 +- ...ex.md.bcdaa8d8.js => index.md.b89ea33b.js} | 2 +- ...a8d8.lean.js => index.md.b89ea33b.lean.js} | 2 +- assets/javascript_notes_1_1-1.md.442433d3.js | 7 + ...avascript_notes_1_1-1.md.442433d3.lean.js} | 2 +- assets/javascript_notes_1_1-1.md.444635ea.js | 7 - ... => javascript_notes_1_1-2.md.cf1c6a03.js} | 2 +- ...avascript_notes_1_1-2.md.cf1c6a03.lean.js} | 2 +- ...md.5b353799.js => jp_index.md.f593c74c.js} | 2 +- ...9.lean.js => jp_index.md.f593c74c.lean.js} | 2 +- ....md.d668d571.js => roadmap.md.233c3dec.js} | 2 +- ...71.lean.js => roadmap.md.233c3dec.lean.js} | 2 +- ...8.js => save_reading_index.md.684b6d50.js} | 2 +- ...=> save_reading_index.md.684b6d50.lean.js} | 2 +- ...=> save_reading_outliers_1.md.9f6d6e06.js} | 2 +- ...ve_reading_outliers_1.md.9f6d6e06.lean.js} | 2 +- ...=> save_reading_outliers_2.md.0f26746f.js} | 2 +- ...ve_reading_outliers_2.md.0f26746f.lean.js} | 2 +- ...=> save_reading_outliers_3.md.ea35e051.js} | 2 +- ...ve_reading_outliers_3.md.ea35e051.lean.js} | 2 +- ...=> save_reading_outliers_4.md.8f24b5aa.js} | 2 +- ...ve_reading_outliers_4.md.8f24b5aa.lean.js} | 2 +- assets/style.41a6cfc6.css | 1 + assets/style.bd240186.css | 1 - development/aws/acknowledgement.html | 12 +- development/aws/appendix.html | 68 +- development/aws/assignments.html | 12 +- development/aws/author.html | 12 +- development/aws/aws-batch.html | 802 +- development/aws/aws-get-started.html | 264 +- development/aws/closing.html | 12 +- development/aws/cloud.html | 12 +- development/aws/docker-system.html | 116 +- development/aws/handson-bashoutter.html | 764 +- development/aws/handson-ec2.html | 368 +- development/aws/handson-jupyter.html | 436 +- development/aws/handson-qabot.html | 310 +- development/aws/handson-serverless.html | 380 +- development/aws/index.html | 12 +- development/aws/license.html | 12 +- development/aws/main.html | 3844 +-- development/aws/scientific-computing.html | 12 +- development/aws/serverless.html | 12 +- development/aws/webserver.html | 12 +- development/file-naming-convention.html | 144 +- development/proxy4shell-terminal.html | 121 + development/rclone-for-r2.html | 112 +- feed.xml | 21484 ++++++++-------- getting-started.html | 32 +- hashmap.json | 2 +- index.html | 12 +- javascript/notes/1/1-1.html | 24 +- javascript/notes/1/1-2.html | 12 +- jp/index.html | 12 +- roadmap.html | 12 +- save/reading/index.html | 12 +- save/reading/outliers/1.html | 12 +- save/reading/outliers/2.html | 12 +- save/reading/outliers/3.html | 12 +- save/reading/outliers/4.html | 12 +- sitemap.xml | 2 +- 294 files changed, 22602 insertions(+), 22051 deletions(-) create mode 100644 assets/2023-11-02-04-44-14.08b67c2b.png create mode 100644 assets/2023-11-04-00-42-58.d7bf77fb.png create mode 100644 assets/2023-11-04-01-32-28.da2149a9.png create mode 100644 assets/2023-11-04-03-15-12.77ab4cd9.png create mode 100644 assets/2023-11-04-03-49-38.78c93d29.png create mode 100644 assets/2023-11-04-04-27-59.3d817820.png create mode 100644 assets/2023-11-04-05-01-04.fd5f8fb7.png rename assets/{academic_chemistry_index.md.ca0457b9.js => academic_chemistry_index.md.56f381d7.js} (92%) rename assets/{academic_chemistry_index.md.ca0457b9.lean.js => academic_chemistry_index.md.56f381d7.lean.js} (92%) rename assets/{academic_chemistry_notes_12-5.md.4c698a37.js => academic_chemistry_notes_12-5.md.f9fc6ef4.js} (99%) rename assets/{academic_chemistry_notes_12-5.md.4c698a37.lean.js => academic_chemistry_notes_12-5.md.f9fc6ef4.lean.js} (99%) rename assets/{academic_chemistry_problems_02-20.md.7015a0e8.js => academic_chemistry_problems_02-20.md.86be96e0.js} (99%) rename assets/{academic_chemistry_problems_02-20.md.7015a0e8.lean.js => academic_chemistry_problems_02-20.md.86be96e0.lean.js} (99%) rename assets/{academic_chemistry_problems_03-02-1.md.054898d2.js => academic_chemistry_problems_03-02-1.md.a9ee56be.js} (99%) rename assets/{academic_chemistry_problems_03-02-1.md.054898d2.lean.js => academic_chemistry_problems_03-02-1.md.a9ee56be.lean.js} (99%) rename assets/{academic_chemistry_problems_03-02-2.md.26afa053.js => academic_chemistry_problems_03-02-2.md.a4b8c746.js} (99%) rename assets/{academic_chemistry_problems_03-02-2.md.26afa053.lean.js => academic_chemistry_problems_03-02-2.md.a4b8c746.lean.js} (99%) rename assets/{academic_chemistry_problems_03-02-3.md.5c40792d.js => academic_chemistry_problems_03-02-3.md.152b3eb2.js} (99%) rename assets/{academic_chemistry_problems_03-02-3.md.5c40792d.lean.js => academic_chemistry_problems_03-02-3.md.152b3eb2.lean.js} (99%) rename assets/{academic_literature_index.md.72bce40a.js => academic_literature_index.md.bd51fa1c.js} (92%) rename assets/{academic_literature_index.md.72bce40a.lean.js => academic_literature_index.md.bd51fa1c.lean.js} (92%) rename assets/{academic_literature_writing_methods-of-development.md.b70ad7bf.js => academic_literature_writing_methods-of-development.md.bcfb091e.js} (99%) rename assets/{academic_literature_writing_methods-of-development.md.b70ad7bf.lean.js => academic_literature_writing_methods-of-development.md.bcfb091e.lean.js} (90%) rename assets/{academic_physics_index.md.62b4f030.js => academic_physics_index.md.6ec0ff5a.js} (92%) rename assets/{academic_physics_index.md.62b4f030.lean.js => academic_physics_index.md.6ec0ff5a.lean.js} (92%) rename assets/{academic_physics_ipho-formulas-jpn_1.md.fa61cf48.js => academic_physics_ipho-formulas-jpn_1.md.b1c8984c.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_1.md.fa61cf48.lean.js => academic_physics_ipho-formulas-jpn_1.md.b1c8984c.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_10.md.5252ef94.js => academic_physics_ipho-formulas-jpn_10.md.2eaa8ad2.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_10.md.5252ef94.lean.js => academic_physics_ipho-formulas-jpn_10.md.2eaa8ad2.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_11.md.5f6411f3.js => academic_physics_ipho-formulas-jpn_11.md.3b777f56.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_11.md.5f6411f3.lean.js => academic_physics_ipho-formulas-jpn_11.md.3b777f56.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_12.md.b01af32f.js => academic_physics_ipho-formulas-jpn_12.md.449de813.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_12.md.b01af32f.lean.js => academic_physics_ipho-formulas-jpn_12.md.449de813.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_13.md.5d106b26.js => academic_physics_ipho-formulas-jpn_13.md.20d2560f.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_13.md.5d106b26.lean.js => academic_physics_ipho-formulas-jpn_13.md.20d2560f.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_2.md.f9a6af54.js => academic_physics_ipho-formulas-jpn_2.md.6d273404.js} (97%) rename assets/{academic_physics_ipho-formulas-jpn_2.md.f9a6af54.lean.js => academic_physics_ipho-formulas-jpn_2.md.6d273404.lean.js} (97%) rename assets/{academic_physics_ipho-formulas-jpn_3.md.aadd6536.js => academic_physics_ipho-formulas-jpn_3.md.6485844d.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_3.md.aadd6536.lean.js => academic_physics_ipho-formulas-jpn_3.md.6485844d.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_4.md.67c0b4f9.js => academic_physics_ipho-formulas-jpn_4.md.47f0821f.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_4.md.67c0b4f9.lean.js => academic_physics_ipho-formulas-jpn_4.md.47f0821f.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_5.md.6c32aa10.js => academic_physics_ipho-formulas-jpn_5.md.948cb5df.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_5.md.6c32aa10.lean.js => academic_physics_ipho-formulas-jpn_5.md.948cb5df.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_6.md.bc519d11.js => academic_physics_ipho-formulas-jpn_6.md.d563d3f1.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_6.md.bc519d11.lean.js => academic_physics_ipho-formulas-jpn_6.md.d563d3f1.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_7.md.353d535e.js => academic_physics_ipho-formulas-jpn_7.md.b0bd68dd.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_7.md.353d535e.lean.js => academic_physics_ipho-formulas-jpn_7.md.b0bd68dd.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_8.md.f1df91b7.js => academic_physics_ipho-formulas-jpn_8.md.f05c02fb.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_8.md.f1df91b7.lean.js => academic_physics_ipho-formulas-jpn_8.md.f05c02fb.lean.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_9.md.da4d857a.js => academic_physics_ipho-formulas-jpn_9.md.083302ab.js} (99%) rename assets/{academic_physics_ipho-formulas-jpn_9.md.da4d857a.lean.js => academic_physics_ipho-formulas-jpn_9.md.083302ab.lean.js} (99%) rename assets/{academic_vocabulary_2023_02_2023-02-27.md.06541670.js => academic_vocabulary_2023_02_2023-02-27.md.3ec19aaf.js} (98%) rename assets/{academic_vocabulary_2023_02_2023-02-27.md.06541670.lean.js => academic_vocabulary_2023_02_2023-02-27.md.3ec19aaf.lean.js} (93%) rename assets/{academic_vocabulary_index.md.f4afb44a.lean.js => academic_vocabulary_index.md.37eb0530.js} (92%) rename assets/{academic_vocabulary_index.md.f4afb44a.js => academic_vocabulary_index.md.37eb0530.lean.js} (92%) rename assets/{app.6020b1dd.js => app.11c168a7.js} (99%) create mode 100644 assets/application_markdown-it-katex_how-to-use.md.b10dd06e.js rename assets/{application_markdown-it-katex_how-to-use.md.e6ab0018.lean.js => application_markdown-it-katex_how-to-use.md.b10dd06e.lean.js} (76%) delete mode 100644 assets/application_markdown-it-katex_how-to-use.md.e6ab0018.js rename assets/{application_markdown-it-katex_support-function.md.009fe258.js => application_markdown-it-katex_support-function.md.59634b4a.js} (99%) rename assets/{application_markdown-it-katex_support-function.md.009fe258.lean.js => application_markdown-it-katex_support-function.md.59634b4a.lean.js} (99%) rename assets/{application_markdown-it-katex_support-table.md.52b042b8.js => application_markdown-it-katex_support-table.md.419e3a5e.js} (99%) rename assets/{application_markdown-it-katex_support-table.md.52b042b8.lean.js => application_markdown-it-katex_support-table.md.419e3a5e.lean.js} (99%) delete mode 100644 assets/application_markdown-it-katex_tips.md.4fa4c33c.js create mode 100644 assets/application_markdown-it-katex_tips.md.d87fb855.js rename assets/{application_markdown-it-katex_tips.md.4fa4c33c.lean.js => application_markdown-it-katex_tips.md.d87fb855.lean.js} (58%) delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.105e6b7f.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.105e6b7f.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.a42ad2a7.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.a42ad2a7.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.2a5fd9c3.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.2a5fd9c3.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.b6b7a28c.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.b6b7a28c.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.07068d46.js rename assets/{application_vitepress-plugin-shiki-twoslash_api_emit.md.8d757f81.lean.js => application_vitepress-plugin-shiki-twoslash_api_emit.md.07068d46.lean.js} (59%) delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.8d757f81.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.230e0002.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.230e0002.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.8032d46f.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.8032d46f.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.b534e723.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.b534e723.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.d69b2a67.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.d69b2a67.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.8b741477.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.8b741477.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.d3641bab.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.d3641bab.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.48f61f4c.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.48f61f4c.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.aea0802f.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.aea0802f.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.8c3dbc97.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.8c3dbc97.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.9bd11a96.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.9bd11a96.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_types.md.9dbcbe1c.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_types.md.9dbcbe1c.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_types.md.a1a99084.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_api_types.md.a1a99084.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.52b87b95.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.52b87b95.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.a683705b.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.a683705b.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.42f9e642.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.42f9e642.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.e7b86a5d.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.e7b86a5d.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.287ab776.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.287ab776.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.58ed95fc.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.58ed95fc.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.6731e737.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.6731e737.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.a9cd6c63.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.a9cd6c63.lean.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_index.md.7fc07d32.js delete mode 100644 assets/application_vitepress-plugin-shiki-twoslash_index.md.7fc07d32.lean.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_index.md.e8d8a5ec.js create mode 100644 assets/application_vitepress-plugin-shiki-twoslash_index.md.e8d8a5ec.lean.js rename assets/chunks/{VPAlgoliaSearchBox.a4c0242a.js => VPAlgoliaSearchBox.c32b1d6a.js} (99%) rename assets/chunks/{theme.7de1b093.js => theme.c3ca1c74.js} (93%) rename assets/{development_aws_acknowledgement.md.daba60ba.js => development_aws_acknowledgement.md.ebd64504.js} (97%) rename assets/{development_aws_acknowledgement.md.daba60ba.lean.js => development_aws_acknowledgement.md.ebd64504.lean.js} (91%) create mode 100644 assets/development_aws_appendix.md.071021e4.js create mode 100644 assets/development_aws_appendix.md.071021e4.lean.js delete mode 100644 assets/development_aws_appendix.md.568c3e80.js delete mode 100644 assets/development_aws_appendix.md.568c3e80.lean.js rename assets/{development_aws_assignments.md.35fe9703.js => development_aws_assignments.md.fcb27d2d.js} (92%) rename assets/{development_aws_assignments.md.35fe9703.lean.js => development_aws_assignments.md.fcb27d2d.lean.js} (92%) rename assets/{development_aws_author.md.025b6bde.js => development_aws_author.md.a292956b.js} (95%) rename assets/{development_aws_author.md.025b6bde.lean.js => development_aws_author.md.a292956b.lean.js} (95%) create mode 100644 assets/development_aws_aws-batch.md.76d54c51.js create mode 100644 assets/development_aws_aws-batch.md.76d54c51.lean.js delete mode 100644 assets/development_aws_aws-batch.md.de2d649a.js delete mode 100644 assets/development_aws_aws-batch.md.de2d649a.lean.js create mode 100644 assets/development_aws_aws-get-started.md.5e1dfdb2.js create mode 100644 assets/development_aws_aws-get-started.md.5e1dfdb2.lean.js delete mode 100644 assets/development_aws_aws-get-started.md.e1a56953.js delete mode 100644 assets/development_aws_aws-get-started.md.e1a56953.lean.js rename assets/{development_aws_closing.md.cf9dad64.js => development_aws_closing.md.0cdd4f54.js} (91%) rename assets/{development_aws_closing.md.cf9dad64.lean.js => development_aws_closing.md.0cdd4f54.lean.js} (91%) rename assets/{development_aws_cloud.md.e679b136.js => development_aws_cloud.md.148d68f2.js} (99%) rename assets/{development_aws_cloud.md.e679b136.lean.js => development_aws_cloud.md.148d68f2.lean.js} (92%) delete mode 100644 assets/development_aws_docker-system.md.4275fd21.lean.js rename assets/{development_aws_docker-system.md.4275fd21.js => development_aws_docker-system.md.dcee24fc.js} (64%) create mode 100644 assets/development_aws_docker-system.md.dcee24fc.lean.js create mode 100644 assets/development_aws_handson-bashoutter.md.890a8ec8.js rename assets/{development_aws_handson-bashoutter.md.d59bc53b.lean.js => development_aws_handson-bashoutter.md.890a8ec8.lean.js} (50%) delete mode 100644 assets/development_aws_handson-bashoutter.md.d59bc53b.js delete mode 100644 assets/development_aws_handson-ec2.md.2a763e5b.js create mode 100644 assets/development_aws_handson-ec2.md.43188290.js rename assets/{development_aws_handson-ec2.md.2a763e5b.lean.js => development_aws_handson-ec2.md.43188290.lean.js} (58%) delete mode 100644 assets/development_aws_handson-jupyter.md.7f479319.js delete mode 100644 assets/development_aws_handson-jupyter.md.7f479319.lean.js create mode 100644 assets/development_aws_handson-jupyter.md.e87bcd1f.js create mode 100644 assets/development_aws_handson-jupyter.md.e87bcd1f.lean.js create mode 100644 assets/development_aws_handson-qabot.md.27ff1082.js create mode 100644 assets/development_aws_handson-qabot.md.27ff1082.lean.js delete mode 100644 assets/development_aws_handson-qabot.md.3c125433.js delete mode 100644 assets/development_aws_handson-qabot.md.3c125433.lean.js delete mode 100644 assets/development_aws_handson-serverless.md.330af1e8.js delete mode 100644 assets/development_aws_handson-serverless.md.330af1e8.lean.js create mode 100644 assets/development_aws_handson-serverless.md.7fbfa1f9.js create mode 100644 assets/development_aws_handson-serverless.md.7fbfa1f9.lean.js rename assets/{development_aws_index.md.1f9e71a6.js => development_aws_index.md.0fcf5beb.js} (74%) rename assets/{development_aws_index.md.1f9e71a6.lean.js => development_aws_index.md.0fcf5beb.lean.js} (85%) rename assets/{development_aws_license.md.5f519b50.js => development_aws_license.md.38e84b81.js} (95%) rename assets/{development_aws_license.md.5f519b50.lean.js => development_aws_license.md.38e84b81.lean.js} (95%) create mode 100644 assets/development_aws_main.md.587d14dd.js create mode 100644 assets/development_aws_main.md.587d14dd.lean.js delete mode 100644 assets/development_aws_main.md.58c079df.js delete mode 100644 assets/development_aws_main.md.58c079df.lean.js rename assets/{development_aws_scientific-computing.md.1b192c5b.js => development_aws_scientific-computing.md.194874e2.js} (99%) rename assets/{development_aws_scientific-computing.md.1b192c5b.lean.js => development_aws_scientific-computing.md.194874e2.lean.js} (94%) rename assets/{development_aws_serverless.md.715b8a8d.js => development_aws_serverless.md.a89d6134.js} (99%) rename assets/{development_aws_serverless.md.715b8a8d.lean.js => development_aws_serverless.md.a89d6134.lean.js} (93%) rename assets/{development_aws_webserver.md.441ce29f.js => development_aws_webserver.md.89157904.js} (99%) rename assets/{development_aws_webserver.md.441ce29f.lean.js => development_aws_webserver.md.89157904.lean.js} (93%) rename assets/{development_file-naming-convention.md.ff928233.js => development_file-naming-convention.md.0fb858f4.js} (57%) rename assets/{development_file-naming-convention.md.ff928233.lean.js => development_file-naming-convention.md.0fb858f4.lean.js} (64%) create mode 100644 assets/development_proxy4shell-terminal.md.a93dc7e4.js create mode 100644 assets/development_proxy4shell-terminal.md.a93dc7e4.lean.js create mode 100644 assets/development_rclone-for-r2.md.65c0da34.js create mode 100644 assets/development_rclone-for-r2.md.65c0da34.lean.js delete mode 100644 assets/development_rclone-for-r2.md.72ca2dcc.js delete mode 100644 assets/development_rclone-for-r2.md.72ca2dcc.lean.js delete mode 100644 assets/getting-started.md.54a05997.js create mode 100644 assets/getting-started.md.975024a7.js rename assets/{getting-started.md.54a05997.lean.js => getting-started.md.975024a7.lean.js} (63%) rename assets/{index.md.bcdaa8d8.js => index.md.b89ea33b.js} (96%) rename assets/{index.md.bcdaa8d8.lean.js => index.md.b89ea33b.lean.js} (96%) create mode 100644 assets/javascript_notes_1_1-1.md.442433d3.js rename assets/{javascript_notes_1_1-1.md.444635ea.lean.js => javascript_notes_1_1-1.md.442433d3.lean.js} (91%) delete mode 100644 assets/javascript_notes_1_1-1.md.444635ea.js rename assets/{javascript_notes_1_1-2.md.cddd09d6.js => javascript_notes_1_1-2.md.cf1c6a03.js} (84%) rename assets/{javascript_notes_1_1-2.md.cddd09d6.lean.js => javascript_notes_1_1-2.md.cf1c6a03.lean.js} (84%) rename assets/{jp_index.md.5b353799.js => jp_index.md.f593c74c.js} (97%) rename assets/{jp_index.md.5b353799.lean.js => jp_index.md.f593c74c.lean.js} (97%) rename assets/{roadmap.md.d668d571.js => roadmap.md.233c3dec.js} (98%) rename assets/{roadmap.md.d668d571.lean.js => roadmap.md.233c3dec.lean.js} (91%) rename assets/{save_reading_index.md.d900b2c8.js => save_reading_index.md.684b6d50.js} (92%) rename assets/{save_reading_index.md.d900b2c8.lean.js => save_reading_index.md.684b6d50.lean.js} (92%) rename assets/{save_reading_outliers_1.md.64c11331.js => save_reading_outliers_1.md.9f6d6e06.js} (99%) rename assets/{save_reading_outliers_1.md.64c11331.lean.js => save_reading_outliers_1.md.9f6d6e06.lean.js} (94%) rename assets/{save_reading_outliers_2.md.74187620.js => save_reading_outliers_2.md.0f26746f.js} (99%) rename assets/{save_reading_outliers_2.md.74187620.lean.js => save_reading_outliers_2.md.0f26746f.lean.js} (94%) rename assets/{save_reading_outliers_3.md.0cab1bb8.js => save_reading_outliers_3.md.ea35e051.js} (99%) rename assets/{save_reading_outliers_3.md.0cab1bb8.lean.js => save_reading_outliers_3.md.ea35e051.lean.js} (94%) rename assets/{save_reading_outliers_4.md.d65868f7.js => save_reading_outliers_4.md.8f24b5aa.js} (99%) rename assets/{save_reading_outliers_4.md.d65868f7.lean.js => save_reading_outliers_4.md.8f24b5aa.lean.js} (94%) create mode 100644 assets/style.41a6cfc6.css delete mode 100644 assets/style.bd240186.css create mode 100644 development/proxy4shell-terminal.html diff --git a/404.html b/404.html index 7199f04d..683e81fe 100644 --- a/404.html +++ b/404.html @@ -5,9 +5,9 @@ 404 | Toshiki's Note - + - + @@ -31,8 +31,8 @@ -
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.
- +
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.
+ \ No newline at end of file diff --git a/academic/chemistry/index.html b/academic/chemistry/index.html index 754fd694..fbfbf998 100644 --- a/academic/chemistry/index.html +++ b/academic/chemistry/index.html @@ -5,15 +5,15 @@ Welcome to Chemistry | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Welcome to Chemistry

Author:Anda Toshiki
Updated:4 minutes ago
Words:3
Reading:1 min
- +
Skip to content

Welcome to Chemistry

Author:Anda Toshiki
Updated:2 minutes ago
Words:3
Reading:1 min
+ \ No newline at end of file diff --git a/academic/chemistry/notes/12-5.html b/academic/chemistry/notes/12-5.html index 43304af4..5667f415 100644 --- a/academic/chemistry/notes/12-5.html +++ b/academic/chemistry/notes/12-5.html @@ -5,15 +5,15 @@ 12-5: Reaction Mechanism | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

12-5: Reaction Mechanism

Author:Anda Toshiki
Updated:4 minutes ago
Words:1.9k
Reading:11 min

12-5-1: Learning Objectives

Learning Objectives

One of the major reasons for studying chemical kinetics is to use measurements of the macroscopic properties of a system, such as the rate of change in the concentration of reactants or products with time, to discover the sequence of events that occur at the molecular level during a reaction. This molecular description is the mechanism of the reaction; it describes how individual atoms, ions, or molecules interact to form particular products. The stepwise changes are collectively called the reaction mechanism.

In an internal combustion engine, for example, isooctane reacts with oxygen to give carbon dioxide and water:

2C8H18(l)+25O2( g)16CO2( g)+18H2O(g)2 \mathrm{C}_{8} \mathrm{H}_{18}(\mathrm{l})+25 \mathrm{O}_{2}(\mathrm{~g}) \longrightarrow 16 \mathrm{CO}_{2}(\mathrm{~g})+18 \mathrm{H}_{2} \mathrm{O}(\mathrm{g})

For this reaction to occur in a single step, 25 dioxygen molecules and 2 isooctane molecules would have to collide simultaneously and be converted to 34 molecules of product, which is very unlikely. It is more likely that a complex series of reactions takes place in a stepwise fashion. Each individual reaction, which is called an elementary reaction, involves one, two, or (rarely) three atoms, molecules, or ions. The overall sequence of elementary reactions is the mechanism of the reaction. The sum of the individual steps, or elementary reactions, in the mechanism must give the balanced chemical equation for the overall reaction.

The overall sequence of elementary reactions is the mechanism of the reaction.

12-5-2: Molecularity and the Rate-Determining Step

To demonstrate how the analysis of elementary reactions helps us determine the overall reaction mechanism, we will examine the much simpler reaction of carbon monoxide with nitrogen dioxide.

2CO+2NO22CO2+N2O4\mathrm{2CO + 2NO_2 \rightarrow 2CO_2 + N_2O_4}

From the balanced chemical equation, one might expect the reaction to occur via a collision of one molecule of NO2\mathrm{NO}_{2} with a molecule of CO\mathrm{CO} that results in the transfer of an oxygen atom from nitrogen to carbon. The experimentally determined rate law for the reaction, however, is as follows:

 rate =k[NO2]2\text { rate }=k\left[\mathrm{NO}_{2}\right]^{2}

The fact that the reaction is second order in [NO2]\left[\mathrm{NO}_{2}\right] and independent of [CO][\mathrm{CO}] tells us that it does not occur by the simple collision model outlined previously. If it did, its predicted rate law would be

 rate =k[NO2][CO].\text { rate }=k\left[\mathrm{NO}_{2}\right][\mathrm{CO}] .

The following two-step mechanism is consistent with the rate law if step 1 is much slower than step 2:

15-2-1: Two-Step Mechanism

StepsReactionReaction Type
step 1NO2+NO2 slow NO3+NO\mathrm{NO}_{2}+\mathrm{NO}_{2} \stackrel{\text { slow }}{\longrightarrow} \mathrm{NO}_{3}+\mathrm{NO}elementary reaction
step 2NO3+CONO2+CO2\underline{\mathrm{NO}_{3}+\mathrm{CO} \rightarrow \mathrm{NO}_{2}+\mathrm{CO}_{2}}elementary reaction
sumNO2+CONO+CO2\mathrm{NO}_{2}+\mathrm{CO} \rightarrow \mathrm{NO}+\mathrm{CO}_{2}overall reaction

According to this mechanism, the overall reaction occurs in two steps, or elementary reactions. Summing steps 1 and 2 and canceling on both sides of the equation gives the overall balanced chemical equation for the reaction. The NO3\mathrm{NO_3} molecule is intermediate in the reaction, a species that does not appear in the balanced chemical equation for the overall reaction. It is formed as a product of the first step but is consumed in the second step.

The sum of the elementary reactions in a reaction mechanism must give the overall balanced chemical equation of the reaction.

12-5-3: Using Molecularity to Describe a Rate Law

The molecularity of an elementary reaction is the number of molecules that collide during that step in the mechanism. If there is only a single reactant molecule in an elementary reaction, that step is designated as unimolecular; if there are two reactant molecules, it is bimolecular; and if there are three reactant molecules (a relatively rare situation), it is termolecular. Elementary reactions that involve the simultaneous collision of more than three molecules are highly improbable and have never been observed experimentally. (To understand why, try to make three or more marbles or pool balls collide with one another simultaneously!)

About the image

The Basis for Writing Rate Laws of Elementary Reactions. This diagram illustrates how the number of possible collisions per unit time between two reactant species, A and B, depends on the number of A and B particles present. The number of collisions between A and B particles increases as the product of the number of particles, not as the sum. This is why the rate law for an elementary reaction depends on the product of the concentrations of the species that collide in that step. (CC BY-NC-SA; anonymous)

Writing the rate law for an elementary reaction is straightforward because we know how many molecules must collide simultaneously for the elementary reaction to occur; hence the order of the elementary reaction is the same as its molecularity (Table 14.6.1). In contrast, the rate law for the reaction cannot be determined from the balanced chemical equation for the overall reaction. The general rate law for a unimolecular elementary reaction ( A\mathrm{A} \rightarrow products) is

 rate =k[A].\text { rate }=k[A] .

For bimolecular reactions, the reaction rate depends on the number of collisions per unit time, which is proportional to the product of the concentrations of the reactants, as shown in Figure 14.6.1 For a bimolecular elementary reaction of the form A+B\mathrm{A}+\mathrm{B} \rightarrow products, the general rate law is

 rate =k[A][B].\text { rate }=k[A][B] .

Elementary ReactionMolecularityRateReaction Order
A products \mathrm{A} \rightarrow \text { products }Unimolecular rate =k[ A]\text { rate }=k[\mathrm{~A}]first
2 A products 2\mathrm{~A} \rightarrow \text { products }Bimolecular rate =k[ A]2\text { rate }=k[\mathrm{~A}]^2second
A+B products \mathrm{A}+\mathrm{B} \rightarrow \text { products }Bimolecular rate =k[ A][B]\text { rate }=k[\mathrm{~A}][\mathrm{B}]second
2 A+B products 2 \mathrm{~A}+\mathrm{B} \rightarrow \text { products }Termolecular rate =k[ A]2[ B]\text { rate }=k[\mathrm{~A}]^2[\mathrm{~B}]third
A+B+C products \mathrm{A}+\mathrm{B}+\mathrm{C} \rightarrow \text { products }Termolecular rate =k[ A][B][C]\text { rate }=k[\mathrm{~A}][\mathrm{B}][\mathrm{C}]third

For elementary reactions, the order of the elementary reaction is the same as its molecularity. In contrast, the rate law cannot be determined from the balanced chemical equation for the overall reaction (unless it is a single step mechanism and is therefore also an elementary step).

12-5-4: Identifying the Rate-Determining Step

Note the important difference between writing rate laws for elementary reactions and the balanced chemical equation of the overall reaction. Because the balanced chemical equation does not necessarily reveal the individual elementary reactions by which the reaction occurs, we cannot obtain the rate law for a reaction from the overall balanced chemical equation alone. In fact, it is the rate law for the slowest overall reaction, which is the same as the rate law for the slowest step in the reaction mechanism, the ratedetermining step, that must give the experimentally determined rate law for the overall reaction.This statement is true if one step is substantially slower than all the others, typically by a factor of 10 or more. If two or more slow steps have comparable rates, the experimentally determined rate laws can become complex. Our discussion is limited to reactions in which one step can be identified as being substantially slower than any other. The reason for this is that any process that occurs through a sequence of steps can take place no faster than the slowest step in the sequence. In an automotive assembly line, for example, a component cannot be used faster than it is produced. Similarly, blood pressure is regulated by the flow of blood through the smallest passages, the capillaries. Because movement through capillaries constitutes the rate-determining step in blood flow, blood pressure can be regulated by medications that cause the capillaries to contract or dilate. A chemical reaction that occurs via a series of elementary reactions can take place no faster than the slowest step in the series of reactions.

Look at the rate laws for each elementary reaction in the example as well as for the overall reaction.

Rate laws for each elementary reaction in our example as well as for the overall reaction

StepsReactionRate
step 1NO2+NO2k1NO3+NO\mathrm{NO}_2+\mathrm{NO}_2 \stackrel{\mathrm{k}_1}{\rightarrow} \mathrm{NO}_3+\mathrm{NO} rate =k1[NO2]2( predicted) \text { rate }=k_1\left[\mathrm{NO}_2\right]^2(\text { predicted) }
step 2NO3+COk2NO2+CO2\underline{\mathrm{NO}_3+\mathrm{CO} \stackrel{k_2}{\rightarrow} \mathrm{NO}_2+\mathrm{CO}_2} rate =k2[NO3][CO]( predicted )\text { rate }=k_2\left[\mathrm{NO}_3\right][\mathrm{CO}](\text { predicted })
step 3NO2+COkNO+CO2\mathrm{NO}_2+\mathrm{CO} \stackrel{k}{\rightarrow} \mathrm{NO}+\mathrm{CO}_2 rate =k[NO2]2( observed) \text { rate }=k\left[\mathrm{NO}_2\right]^2(\text { observed) }

The experimentally determined rate law for the reaction of NO2\mathrm{NO}_{2} with COC O is the same as the predicted rate law for step 1 . This tells us that the first elementary reaction is the rate-determining step, so kk for the overall reaction must equal k1k_{1}. That is, NO3\mathrm{NO}_{3} is formed slowly in step 1, but once it is formed, it reacts very rapidly with CO in step 2.

Sometimes chemists are able to propose two or more mechanisms that are consistent with the available data. If a proposed mechanism predicts the wrong experimental rate law, however, the mechanism must be incorrect.

12-5-4-1: Example-A Reaction with an Intermediate

In an alternative mechanism for the reaction of NO2\mathrm{NO}_{2} with CO\mathrm{CO} with N2O4\mathrm{N}_{2} \mathrm{O}_{4} appearing as an intermediate.

alternative mechanism for the reaction of NO2\mathrm{NO}_{2} with CO\mathrm{CO} with N2O4\mathrm{N}_{2} \mathrm{O}_{4} appearing as an intermediate.

Write the rate law for each elementary reaction. Is this mechanism consistent with the experimentally determined rate law (rate =k[NO2]2t=\mathrm{k[{NO}_{2}]^{2}t})

Given: elementary reactions Asked for: rate law for each elementary reaction and overall rate law

Strategy

  • Determine the rate law for each elementary reaction in the reaction.

  • Determine which rate law corresponds to the experimentally determined rate law for the reaction. This rate law is the one for the rate-determining step.

Solution

View solution

A The rate law for step 1 is rate =k1[NO2]2=k_{1}\left[\mathrm{NO}_{2}\right]^{2}; for step 2 , it is rate =k2[ N2O4][CO]=k_{2}\left[\mathrm{~N}_{2} \mathrm{O}_{4}\right][\mathrm{CO}].

B If step 1 is slow (and therefore the rate-determining step), then the overall rate law for the reaction will be the same: rate == k1[NO2]2k_{1}\left[\mathrm{NO}_{2}\right]^{2}. This is the same as the experimentally determined rate law. Hence this mechanism, with N2O4\mathrm{N}_{2} \mathrm{O}_{4} as an intermediate, and the one described previously, with NO3\mathrm{NO}_{3} as an intermediate, are kinetically indistinguishable. In this case, further experiments are needed to distinguish between them. For example, the researcher could try to detect the proposed intermediates, NO3\mathrm{NO}_{3} and N2O4\mathrm{N}_{2} \mathrm{O}_{4}, directly.

- +
Skip to content

12-5: Reaction Mechanism

Author:Anda Toshiki
Updated:2 minutes ago
Words:1.9k
Reading:11 min

12-5-1: Learning Objectives

Learning Objectives

One of the major reasons for studying chemical kinetics is to use measurements of the macroscopic properties of a system, such as the rate of change in the concentration of reactants or products with time, to discover the sequence of events that occur at the molecular level during a reaction. This molecular description is the mechanism of the reaction; it describes how individual atoms, ions, or molecules interact to form particular products. The stepwise changes are collectively called the reaction mechanism.

In an internal combustion engine, for example, isooctane reacts with oxygen to give carbon dioxide and water:

2C8H18(l)+25O2( g)16CO2( g)+18H2O(g)2 \mathrm{C}_{8} \mathrm{H}_{18}(\mathrm{l})+25 \mathrm{O}_{2}(\mathrm{~g}) \longrightarrow 16 \mathrm{CO}_{2}(\mathrm{~g})+18 \mathrm{H}_{2} \mathrm{O}(\mathrm{g})

For this reaction to occur in a single step, 25 dioxygen molecules and 2 isooctane molecules would have to collide simultaneously and be converted to 34 molecules of product, which is very unlikely. It is more likely that a complex series of reactions takes place in a stepwise fashion. Each individual reaction, which is called an elementary reaction, involves one, two, or (rarely) three atoms, molecules, or ions. The overall sequence of elementary reactions is the mechanism of the reaction. The sum of the individual steps, or elementary reactions, in the mechanism must give the balanced chemical equation for the overall reaction.

The overall sequence of elementary reactions is the mechanism of the reaction.

12-5-2: Molecularity and the Rate-Determining Step

To demonstrate how the analysis of elementary reactions helps us determine the overall reaction mechanism, we will examine the much simpler reaction of carbon monoxide with nitrogen dioxide.

2CO+2NO22CO2+N2O4\mathrm{2CO + 2NO_2 \rightarrow 2CO_2 + N_2O_4}

From the balanced chemical equation, one might expect the reaction to occur via a collision of one molecule of NO2\mathrm{NO}_{2} with a molecule of CO\mathrm{CO} that results in the transfer of an oxygen atom from nitrogen to carbon. The experimentally determined rate law for the reaction, however, is as follows:

 rate =k[NO2]2\text { rate }=k\left[\mathrm{NO}_{2}\right]^{2}

The fact that the reaction is second order in [NO2]\left[\mathrm{NO}_{2}\right] and independent of [CO][\mathrm{CO}] tells us that it does not occur by the simple collision model outlined previously. If it did, its predicted rate law would be

 rate =k[NO2][CO].\text { rate }=k\left[\mathrm{NO}_{2}\right][\mathrm{CO}] .

The following two-step mechanism is consistent with the rate law if step 1 is much slower than step 2:

15-2-1: Two-Step Mechanism

StepsReactionReaction Type
step 1NO2+NO2 slow NO3+NO\mathrm{NO}_{2}+\mathrm{NO}_{2} \stackrel{\text { slow }}{\longrightarrow} \mathrm{NO}_{3}+\mathrm{NO}elementary reaction
step 2NO3+CONO2+CO2\underline{\mathrm{NO}_{3}+\mathrm{CO} \rightarrow \mathrm{NO}_{2}+\mathrm{CO}_{2}}elementary reaction
sumNO2+CONO+CO2\mathrm{NO}_{2}+\mathrm{CO} \rightarrow \mathrm{NO}+\mathrm{CO}_{2}overall reaction

According to this mechanism, the overall reaction occurs in two steps, or elementary reactions. Summing steps 1 and 2 and canceling on both sides of the equation gives the overall balanced chemical equation for the reaction. The NO3\mathrm{NO_3} molecule is intermediate in the reaction, a species that does not appear in the balanced chemical equation for the overall reaction. It is formed as a product of the first step but is consumed in the second step.

The sum of the elementary reactions in a reaction mechanism must give the overall balanced chemical equation of the reaction.

12-5-3: Using Molecularity to Describe a Rate Law

The molecularity of an elementary reaction is the number of molecules that collide during that step in the mechanism. If there is only a single reactant molecule in an elementary reaction, that step is designated as unimolecular; if there are two reactant molecules, it is bimolecular; and if there are three reactant molecules (a relatively rare situation), it is termolecular. Elementary reactions that involve the simultaneous collision of more than three molecules are highly improbable and have never been observed experimentally. (To understand why, try to make three or more marbles or pool balls collide with one another simultaneously!)

About the image

The Basis for Writing Rate Laws of Elementary Reactions. This diagram illustrates how the number of possible collisions per unit time between two reactant species, A and B, depends on the number of A and B particles present. The number of collisions between A and B particles increases as the product of the number of particles, not as the sum. This is why the rate law for an elementary reaction depends on the product of the concentrations of the species that collide in that step. (CC BY-NC-SA; anonymous)

Writing the rate law for an elementary reaction is straightforward because we know how many molecules must collide simultaneously for the elementary reaction to occur; hence the order of the elementary reaction is the same as its molecularity (Table 14.6.1). In contrast, the rate law for the reaction cannot be determined from the balanced chemical equation for the overall reaction. The general rate law for a unimolecular elementary reaction ( A\mathrm{A} \rightarrow products) is

 rate =k[A].\text { rate }=k[A] .

For bimolecular reactions, the reaction rate depends on the number of collisions per unit time, which is proportional to the product of the concentrations of the reactants, as shown in Figure 14.6.1 For a bimolecular elementary reaction of the form A+B\mathrm{A}+\mathrm{B} \rightarrow products, the general rate law is

 rate =k[A][B].\text { rate }=k[A][B] .

Elementary ReactionMolecularityRateReaction Order
A products \mathrm{A} \rightarrow \text { products }Unimolecular rate =k[ A]\text { rate }=k[\mathrm{~A}]first
2 A products 2\mathrm{~A} \rightarrow \text { products }Bimolecular rate =k[ A]2\text { rate }=k[\mathrm{~A}]^2second
A+B products \mathrm{A}+\mathrm{B} \rightarrow \text { products }Bimolecular rate =k[ A][B]\text { rate }=k[\mathrm{~A}][\mathrm{B}]second
2 A+B products 2 \mathrm{~A}+\mathrm{B} \rightarrow \text { products }Termolecular rate =k[ A]2[ B]\text { rate }=k[\mathrm{~A}]^2[\mathrm{~B}]third
A+B+C products \mathrm{A}+\mathrm{B}+\mathrm{C} \rightarrow \text { products }Termolecular rate =k[ A][B][C]\text { rate }=k[\mathrm{~A}][\mathrm{B}][\mathrm{C}]third

For elementary reactions, the order of the elementary reaction is the same as its molecularity. In contrast, the rate law cannot be determined from the balanced chemical equation for the overall reaction (unless it is a single step mechanism and is therefore also an elementary step).

12-5-4: Identifying the Rate-Determining Step

Note the important difference between writing rate laws for elementary reactions and the balanced chemical equation of the overall reaction. Because the balanced chemical equation does not necessarily reveal the individual elementary reactions by which the reaction occurs, we cannot obtain the rate law for a reaction from the overall balanced chemical equation alone. In fact, it is the rate law for the slowest overall reaction, which is the same as the rate law for the slowest step in the reaction mechanism, the ratedetermining step, that must give the experimentally determined rate law for the overall reaction.This statement is true if one step is substantially slower than all the others, typically by a factor of 10 or more. If two or more slow steps have comparable rates, the experimentally determined rate laws can become complex. Our discussion is limited to reactions in which one step can be identified as being substantially slower than any other. The reason for this is that any process that occurs through a sequence of steps can take place no faster than the slowest step in the sequence. In an automotive assembly line, for example, a component cannot be used faster than it is produced. Similarly, blood pressure is regulated by the flow of blood through the smallest passages, the capillaries. Because movement through capillaries constitutes the rate-determining step in blood flow, blood pressure can be regulated by medications that cause the capillaries to contract or dilate. A chemical reaction that occurs via a series of elementary reactions can take place no faster than the slowest step in the series of reactions.

Look at the rate laws for each elementary reaction in the example as well as for the overall reaction.

Rate laws for each elementary reaction in our example as well as for the overall reaction

StepsReactionRate
step 1NO2+NO2k1NO3+NO\mathrm{NO}_2+\mathrm{NO}_2 \stackrel{\mathrm{k}_1}{\rightarrow} \mathrm{NO}_3+\mathrm{NO} rate =k1[NO2]2( predicted) \text { rate }=k_1\left[\mathrm{NO}_2\right]^2(\text { predicted) }
step 2NO3+COk2NO2+CO2\underline{\mathrm{NO}_3+\mathrm{CO} \stackrel{k_2}{\rightarrow} \mathrm{NO}_2+\mathrm{CO}_2} rate =k2[NO3][CO]( predicted )\text { rate }=k_2\left[\mathrm{NO}_3\right][\mathrm{CO}](\text { predicted })
step 3NO2+COkNO+CO2\mathrm{NO}_2+\mathrm{CO} \stackrel{k}{\rightarrow} \mathrm{NO}+\mathrm{CO}_2 rate =k[NO2]2( observed) \text { rate }=k\left[\mathrm{NO}_2\right]^2(\text { observed) }

The experimentally determined rate law for the reaction of NO2\mathrm{NO}_{2} with COC O is the same as the predicted rate law for step 1 . This tells us that the first elementary reaction is the rate-determining step, so kk for the overall reaction must equal k1k_{1}. That is, NO3\mathrm{NO}_{3} is formed slowly in step 1, but once it is formed, it reacts very rapidly with CO in step 2.

Sometimes chemists are able to propose two or more mechanisms that are consistent with the available data. If a proposed mechanism predicts the wrong experimental rate law, however, the mechanism must be incorrect.

12-5-4-1: Example-A Reaction with an Intermediate

In an alternative mechanism for the reaction of NO2\mathrm{NO}_{2} with CO\mathrm{CO} with N2O4\mathrm{N}_{2} \mathrm{O}_{4} appearing as an intermediate.

alternative mechanism for the reaction of NO2\mathrm{NO}_{2} with CO\mathrm{CO} with N2O4\mathrm{N}_{2} \mathrm{O}_{4} appearing as an intermediate.

Write the rate law for each elementary reaction. Is this mechanism consistent with the experimentally determined rate law (rate =k[NO2]2t=\mathrm{k[{NO}_{2}]^{2}t})

Given: elementary reactions Asked for: rate law for each elementary reaction and overall rate law

Strategy

  • Determine the rate law for each elementary reaction in the reaction.

  • Determine which rate law corresponds to the experimentally determined rate law for the reaction. This rate law is the one for the rate-determining step.

Solution

View solution

A The rate law for step 1 is rate =k1[NO2]2=k_{1}\left[\mathrm{NO}_{2}\right]^{2}; for step 2 , it is rate =k2[ N2O4][CO]=k_{2}\left[\mathrm{~N}_{2} \mathrm{O}_{4}\right][\mathrm{CO}].

B If step 1 is slow (and therefore the rate-determining step), then the overall rate law for the reaction will be the same: rate == k1[NO2]2k_{1}\left[\mathrm{NO}_{2}\right]^{2}. This is the same as the experimentally determined rate law. Hence this mechanism, with N2O4\mathrm{N}_{2} \mathrm{O}_{4} as an intermediate, and the one described previously, with NO3\mathrm{NO}_{3} as an intermediate, are kinetically indistinguishable. In this case, further experiments are needed to distinguish between them. For example, the researcher could try to detect the proposed intermediates, NO3\mathrm{NO}_{3} and N2O4\mathrm{N}_{2} \mathrm{O}_{4}, directly.

+ \ No newline at end of file diff --git a/academic/chemistry/problems/02-20.html b/academic/chemistry/problems/02-20.html index 7230e95f..ad0df4a1 100644 --- a/academic/chemistry/problems/02-20.html +++ b/academic/chemistry/problems/02-20.html @@ -5,15 +5,15 @@ Presentation problem: 02-20 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Presentation problem: 02-20

Author:Anda Toshiki
Updated:4 minutes ago
Words:412
Reading:2 min

Question

At 500 K500 \mathrm{~K} in the presence of a copper surface, ethanol decomposes according to the equation

C2H5OH(g)CH3CHO(g)+H2(g)\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}(\mathrm{g}) \longrightarrow \mathrm{CH}_3 \mathrm{CHO}(g)+\mathrm{H}_2(g)

The pressure of C2H5OH\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH} was measured as a function of time and the following data were obtained:

Time (s)PC2H5OH (torr) P_{\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}} \text { (torr) }
0250.
100.237
200.224
300.211
400.198
500.185

Since the pressure of a gas is directly proportional to the concentration of gas, we can express the rate law for a gaseous reaction in terms of partial pressures. Using the above data, deduce the rate law, the integrated rate law, and the value of the rate constant, all in terms of pressure units in atm and time in seconds. Predict the pressure of C2H5OH\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH} after 900.s900 . \mathrm{s} from the start of the reaction. (Hint: To determine the order of the reaction with respect to C2H5OH\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}, compare how the pressure of C2H5OH\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH} decreases with each time listing.)

Solution

solution graph

Due to the fact that the graph of p[O2]\mathrm{p}\left[\mathrm{O}_2\right] over time is showing R2\mathrm{R}^2 value of 1 we know we have a zero-order reaction. Therefore:

k=p0[C2H5OH]p[C2H5OH]t=250 torr 185 torr 500 s=0.13 torr s 1k=0.13 torr s s1×1 atm760 torr =1.71×104 atm s1 rate =kp(C2H5OH)=kt+p0(C2H5OH)p(C2H5OH)=(1.71×104 atm s1)×900 s+0.33 atmp(C2H5OH)=0.176 atm s1\begin{aligned} & \mathrm{k}=\frac{\mathrm{p}_0\left[\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right]-\mathrm{p}\left[\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right]}{\mathrm{t}}=\frac{250 \text { torr }-185 \text { torr }}{500 \mathrm{~s}}=0.13 \text { torr s }^{-1} \\ & \mathrm{k}=0.13 \text { torr s } \mathrm{s}^{-1} \times \frac{1 \mathrm{~atm}}{760 \text { torr }}=1.71 \times 10^{-4} \mathrm{~atm} \mathrm{~s}^{-1} \\ & \text { rate }=\mathbf{k} \\ & \mathrm{p}\left(\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right)=-\mathrm{kt}+\mathrm{p}_0\left(\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right) \\ & \mathrm{p}\left(\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right)=-\left(1.71 \times 10^{-4} \mathrm{~atm} \mathrm{~s}^{-1}\right) \times 900 \mathrm{~s}+0.33 \mathrm{~atm} \\ & \mathrm{p}\left(\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right)=0.176 \mathrm{~atm} \mathrm{~s}^{-1} \\ & \end{aligned}

- +
Skip to content

Presentation problem: 02-20

Author:Anda Toshiki
Updated:2 minutes ago
Words:412
Reading:2 min

Question

At 500 K500 \mathrm{~K} in the presence of a copper surface, ethanol decomposes according to the equation

C2H5OH(g)CH3CHO(g)+H2(g)\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}(\mathrm{g}) \longrightarrow \mathrm{CH}_3 \mathrm{CHO}(g)+\mathrm{H}_2(g)

The pressure of C2H5OH\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH} was measured as a function of time and the following data were obtained:

Time (s)PC2H5OH (torr) P_{\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}} \text { (torr) }
0250.
100.237
200.224
300.211
400.198
500.185

Since the pressure of a gas is directly proportional to the concentration of gas, we can express the rate law for a gaseous reaction in terms of partial pressures. Using the above data, deduce the rate law, the integrated rate law, and the value of the rate constant, all in terms of pressure units in atm and time in seconds. Predict the pressure of C2H5OH\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH} after 900.s900 . \mathrm{s} from the start of the reaction. (Hint: To determine the order of the reaction with respect to C2H5OH\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}, compare how the pressure of C2H5OH\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH} decreases with each time listing.)

Solution

solution graph

Due to the fact that the graph of p[O2]\mathrm{p}\left[\mathrm{O}_2\right] over time is showing R2\mathrm{R}^2 value of 1 we know we have a zero-order reaction. Therefore:

k=p0[C2H5OH]p[C2H5OH]t=250 torr 185 torr 500 s=0.13 torr s 1k=0.13 torr s s1×1 atm760 torr =1.71×104 atm s1 rate =kp(C2H5OH)=kt+p0(C2H5OH)p(C2H5OH)=(1.71×104 atm s1)×900 s+0.33 atmp(C2H5OH)=0.176 atm s1\begin{aligned} & \mathrm{k}=\frac{\mathrm{p}_0\left[\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right]-\mathrm{p}\left[\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right]}{\mathrm{t}}=\frac{250 \text { torr }-185 \text { torr }}{500 \mathrm{~s}}=0.13 \text { torr s }^{-1} \\ & \mathrm{k}=0.13 \text { torr s } \mathrm{s}^{-1} \times \frac{1 \mathrm{~atm}}{760 \text { torr }}=1.71 \times 10^{-4} \mathrm{~atm} \mathrm{~s}^{-1} \\ & \text { rate }=\mathbf{k} \\ & \mathrm{p}\left(\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right)=-\mathrm{kt}+\mathrm{p}_0\left(\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right) \\ & \mathrm{p}\left(\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right)=-\left(1.71 \times 10^{-4} \mathrm{~atm} \mathrm{~s}^{-1}\right) \times 900 \mathrm{~s}+0.33 \mathrm{~atm} \\ & \mathrm{p}\left(\mathrm{C}_2 \mathrm{H}_5 \mathrm{OH}\right)=0.176 \mathrm{~atm} \mathrm{~s}^{-1} \\ & \end{aligned}

+ \ No newline at end of file diff --git a/academic/chemistry/problems/03-02-1.html b/academic/chemistry/problems/03-02-1.html index 8ef9dc69..89d7ca42 100644 --- a/academic/chemistry/problems/03-02-1.html +++ b/academic/chemistry/problems/03-02-1.html @@ -5,15 +5,15 @@ Problem: 03-02-1 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Problem: 03-02-1

Author:Anda Toshiki
Updated:4 minutes ago
Words:404
Reading:2 min

Question

2 N2O5(g)4NO2(g)+O2(g)2 \mathrm{~N}_2 \mathrm{O}_5(g) \rightarrow 4 \mathrm{NO}_2(g)+\mathrm{O}_2(g)

The decomposition of N2O5(g)\mathrm{N}_2 \mathrm{O}_5(g) is represented by the equation above. A sample of N2O5(g)\mathrm{N}_2 \mathrm{O}_5(g) is monitored as it decomposes, and the concentration of N2O5\mathrm{N}_2 \mathrm{O}_5 as a function of time is recorded. The results are shown in the table below.

Time (s)[N2O5]\mathrm{[N_2O_5]}
01.000
25.00.801
50.00.642
75.00.515

Calculate the average rate of the reaction between 50.050.0 and 75.075.0 seconds.

Solution

a A+b BcC+dDa \mathrm{~A}+b \mathrm{~B} \rightarrow c \mathrm{C}+d \mathrm{D}

the rate of reaction is defined as

 rate =1aΔ[A]Δt=1bΔ[B]Δt=+1cΔ[C]Δt=+1dΔ[D]Δt\color{cyan}\text { rate }=-\frac{1}{a} \frac{\Delta[\mathrm{A}]}{\Delta t}=-\frac{1}{b} \frac{\Delta[\mathrm{B}]}{\Delta t}=+\frac{1}{c} \frac{\Delta[\mathrm{C}]}{\Delta t}=+\frac{1}{d} \frac{\Delta[\mathrm{D}]}{\Delta t}

Notice that the rate of change in concentration of each species is divided by its coefficient from the balanced chemical equation ( aa, b,cb, c, or dd ). This ensures that the calculated reaction rate is the same no matter which reactant or product is monitored for changes in concentration. In this case, the monitored species was N2O5\mathrm{N}_2 \mathrm{O}_5. With that in mind, let's write the reaction rate in terms of the rate of change in concentration of N2O5\mathrm{N}_2 \mathrm{O}_5 :

 rate =12Δ[N2O5]Δt\text { rate }=-\frac{1}{2} \frac{\Delta\left[\mathrm{N}_2 \mathrm{O}_5\right]}{\Delta t}

Since the coefficient for N2O5\mathrm{N}_2 \mathrm{O}_5 in the balanced equation is 2 , we divided the rate of change in concentration of N2O5\mathrm{N}_2 \mathrm{O}_5 by 2 . Additionally, since N2O5\mathrm{N}_2 \mathrm{O}_5 is being consumed in the reaction, we included a negative sign in front of the expression.

Now, let's plug in the information from the table to calculate the average reaction rate between 50.050.0 and 75.075.0 seconds:

 rate =12(0.515M0.642M)(75.0 s50.0 s)=2.54×103M s1\begin{aligned} \text { rate } & =-\frac{1}{2} \frac{(0.515 M-0.642 M)}{(75.0 \mathrm{~s}-50.0 \mathrm{~s})} \\ & =2.54 \times 10^{-3} M \mathrm{~s}^{-1} \end{aligned}

So, the average rate of the reaction between 50.050.0 and 75.075.0 seconds is 2.54×103Ms1\bold{2.54 \times 10^{-3} \mathrm{M} \mathrm{s}^{-1}}.

- +
Skip to content

Problem: 03-02-1

Author:Anda Toshiki
Updated:2 minutes ago
Words:404
Reading:2 min

Question

2 N2O5(g)4NO2(g)+O2(g)2 \mathrm{~N}_2 \mathrm{O}_5(g) \rightarrow 4 \mathrm{NO}_2(g)+\mathrm{O}_2(g)

The decomposition of N2O5(g)\mathrm{N}_2 \mathrm{O}_5(g) is represented by the equation above. A sample of N2O5(g)\mathrm{N}_2 \mathrm{O}_5(g) is monitored as it decomposes, and the concentration of N2O5\mathrm{N}_2 \mathrm{O}_5 as a function of time is recorded. The results are shown in the table below.

Time (s)[N2O5]\mathrm{[N_2O_5]}
01.000
25.00.801
50.00.642
75.00.515

Calculate the average rate of the reaction between 50.050.0 and 75.075.0 seconds.

Solution

a A+b BcC+dDa \mathrm{~A}+b \mathrm{~B} \rightarrow c \mathrm{C}+d \mathrm{D}

the rate of reaction is defined as

 rate =1aΔ[A]Δt=1bΔ[B]Δt=+1cΔ[C]Δt=+1dΔ[D]Δt\color{cyan}\text { rate }=-\frac{1}{a} \frac{\Delta[\mathrm{A}]}{\Delta t}=-\frac{1}{b} \frac{\Delta[\mathrm{B}]}{\Delta t}=+\frac{1}{c} \frac{\Delta[\mathrm{C}]}{\Delta t}=+\frac{1}{d} \frac{\Delta[\mathrm{D}]}{\Delta t}

Notice that the rate of change in concentration of each species is divided by its coefficient from the balanced chemical equation ( aa, b,cb, c, or dd ). This ensures that the calculated reaction rate is the same no matter which reactant or product is monitored for changes in concentration. In this case, the monitored species was N2O5\mathrm{N}_2 \mathrm{O}_5. With that in mind, let's write the reaction rate in terms of the rate of change in concentration of N2O5\mathrm{N}_2 \mathrm{O}_5 :

 rate =12Δ[N2O5]Δt\text { rate }=-\frac{1}{2} \frac{\Delta\left[\mathrm{N}_2 \mathrm{O}_5\right]}{\Delta t}

Since the coefficient for N2O5\mathrm{N}_2 \mathrm{O}_5 in the balanced equation is 2 , we divided the rate of change in concentration of N2O5\mathrm{N}_2 \mathrm{O}_5 by 2 . Additionally, since N2O5\mathrm{N}_2 \mathrm{O}_5 is being consumed in the reaction, we included a negative sign in front of the expression.

Now, let's plug in the information from the table to calculate the average reaction rate between 50.050.0 and 75.075.0 seconds:

 rate =12(0.515M0.642M)(75.0 s50.0 s)=2.54×103M s1\begin{aligned} \text { rate } & =-\frac{1}{2} \frac{(0.515 M-0.642 M)}{(75.0 \mathrm{~s}-50.0 \mathrm{~s})} \\ & =2.54 \times 10^{-3} M \mathrm{~s}^{-1} \end{aligned}

So, the average rate of the reaction between 50.050.0 and 75.075.0 seconds is 2.54×103Ms1\bold{2.54 \times 10^{-3} \mathrm{M} \mathrm{s}^{-1}}.

+ \ No newline at end of file diff --git a/academic/chemistry/problems/03-02-2.html b/academic/chemistry/problems/03-02-2.html index 18cbbc3f..67ef2f2a 100644 --- a/academic/chemistry/problems/03-02-2.html +++ b/academic/chemistry/problems/03-02-2.html @@ -5,15 +5,15 @@ Problem: 03-02-2 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Problem: 03-02-2

Author:Anda Toshiki
Updated:4 minutes ago
Words:205
Reading:1 min

Question

The rate law for a particular reaction is rate =k[XY]2=k[\mathrm{XY}]^2. In an experiment, the initial rate of the reaction is determined to be 0.16 mol/(Ls)0.16 \mathrm{~mol} /(\mathrm{L} \cdot \mathrm{s}) when the initial concentration of XY\mathrm{XY} is 0.40 mol/L0.40 \mathrm{~mol} / \mathrm{L}.

  • What is the value of the rate constant, kk, for the reaction?
    • 0.10 L/(mols)0.10 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})
    • 0.40 L/(mols)0.40 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})
    • 1.0 L/(mols)1.0 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})
    • 2.5 L/(mols)2.5 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})

Solution

lo tind the value of the rate constant for the reaction, let's first solve the rate law for kk :

k= rate [XY]2k=\frac{\text { rate }}{[\mathrm{XY}]^2}

Next, let's plug in the initial rate and concentration given in the text:

k=0.16 mol/(Ls)(0.40 mol/L)2=0.16 mol/(Ls)0.16 mol2/L2=1.0 L/(mols)\begin{aligned} k & =\frac{0.16 \mathrm{~mol} /(\mathrm{L} \cdot \mathrm{s})}{(0.40 \mathrm{~mol} / \mathrm{L})^2} \\ & =\frac{0.16 \mathrm{~mol} /(\mathrm{L} \cdot \mathrm{s})}{0.16 \mathrm{~mol}^2 / \mathrm{L}^2} \\ & =1.0 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s}) \end{aligned}

So, the value of the rate constant for the reaction is 1.0 L/(mols)1.0 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})

- +
Skip to content

Problem: 03-02-2

Author:Anda Toshiki
Updated:2 minutes ago
Words:205
Reading:1 min

Question

The rate law for a particular reaction is rate =k[XY]2=k[\mathrm{XY}]^2. In an experiment, the initial rate of the reaction is determined to be 0.16 mol/(Ls)0.16 \mathrm{~mol} /(\mathrm{L} \cdot \mathrm{s}) when the initial concentration of XY\mathrm{XY} is 0.40 mol/L0.40 \mathrm{~mol} / \mathrm{L}.

  • What is the value of the rate constant, kk, for the reaction?
    • 0.10 L/(mols)0.10 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})
    • 0.40 L/(mols)0.40 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})
    • 1.0 L/(mols)1.0 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})
    • 2.5 L/(mols)2.5 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})

Solution

lo tind the value of the rate constant for the reaction, let's first solve the rate law for kk :

k= rate [XY]2k=\frac{\text { rate }}{[\mathrm{XY}]^2}

Next, let's plug in the initial rate and concentration given in the text:

k=0.16 mol/(Ls)(0.40 mol/L)2=0.16 mol/(Ls)0.16 mol2/L2=1.0 L/(mols)\begin{aligned} k & =\frac{0.16 \mathrm{~mol} /(\mathrm{L} \cdot \mathrm{s})}{(0.40 \mathrm{~mol} / \mathrm{L})^2} \\ & =\frac{0.16 \mathrm{~mol} /(\mathrm{L} \cdot \mathrm{s})}{0.16 \mathrm{~mol}^2 / \mathrm{L}^2} \\ & =1.0 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s}) \end{aligned}

So, the value of the rate constant for the reaction is 1.0 L/(mols)1.0 \mathrm{~L} /(\mathrm{mol} \cdot \mathrm{s})

+ \ No newline at end of file diff --git a/academic/chemistry/problems/03-02-3.html b/academic/chemistry/problems/03-02-3.html index 95c1b73d..42c6dc2f 100644 --- a/academic/chemistry/problems/03-02-3.html +++ b/academic/chemistry/problems/03-02-3.html @@ -5,15 +5,15 @@ Problem 03-02-3 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Problem 03-02-3

Author:Anda Toshiki
Updated:4 minutes ago
Words:246
Reading:1 min

Question

2X(g)+2Y(g)Q(g)+2R(g)2 \mathrm{X}(g)+2 \mathrm{Y}(g) \rightarrow \mathrm{Q}(g)+2 \mathrm{R}(g)

The reaction represented above is found to be second order with respect to X\mathrm{X} and first order with respect to Y\mathrm{Y}.

What happens to the rate of the reaction when [X][\mathrm{X}] is halved and [Y][\mathrm{Y}] is doubled?

  • It increases by a factor of 4.
  • It decreases by a factor of 2.
  • It decreases by a factor of 4.
  • It does not change.

Solution

To solve this problem, let's first write out the rate law for the reaction. According to the text, the reaction is second order with respect to X\mathrm{X} and first order with respect to Y\mathrm{Y}, so the rate law is rate =k[X]2[Y]=k[\mathrm{X}]^2[\mathrm{Y}]

Now, let's think about how the rate changes when [X][\mathrm{X}] is halved and [Y][\mathrm{Y}] is doubled. Since [X][\mathrm{X}] is raised to the second power in the rate law, halving [X][\mathrm{X}] decreases the reaction rate by a factor of 4 . Similarly, since [Y][\mathrm{Y}] is raised to the first power, doubling [Y][\mathrm{Y}] increases the reaction rate by a factor of 2 . Combined, these changes result in the reaction rate decreasing by a factor of 2 overall. So, when [X][\mathrm{X}] is halved and [Y][\mathrm{Y}] is doubled, the rate of the reaction decreases by a factor of 2 .

- +
Skip to content

Problem 03-02-3

Author:Anda Toshiki
Updated:2 minutes ago
Words:246
Reading:1 min

Question

2X(g)+2Y(g)Q(g)+2R(g)2 \mathrm{X}(g)+2 \mathrm{Y}(g) \rightarrow \mathrm{Q}(g)+2 \mathrm{R}(g)

The reaction represented above is found to be second order with respect to X\mathrm{X} and first order with respect to Y\mathrm{Y}.

What happens to the rate of the reaction when [X][\mathrm{X}] is halved and [Y][\mathrm{Y}] is doubled?

  • It increases by a factor of 4.
  • It decreases by a factor of 2.
  • It decreases by a factor of 4.
  • It does not change.

Solution

To solve this problem, let's first write out the rate law for the reaction. According to the text, the reaction is second order with respect to X\mathrm{X} and first order with respect to Y\mathrm{Y}, so the rate law is rate =k[X]2[Y]=k[\mathrm{X}]^2[\mathrm{Y}]

Now, let's think about how the rate changes when [X][\mathrm{X}] is halved and [Y][\mathrm{Y}] is doubled. Since [X][\mathrm{X}] is raised to the second power in the rate law, halving [X][\mathrm{X}] decreases the reaction rate by a factor of 4 . Similarly, since [Y][\mathrm{Y}] is raised to the first power, doubling [Y][\mathrm{Y}] increases the reaction rate by a factor of 2 . Combined, these changes result in the reaction rate decreasing by a factor of 2 overall. So, when [X][\mathrm{X}] is halved and [Y][\mathrm{Y}] is doubled, the rate of the reaction decreases by a factor of 2 .

+ \ No newline at end of file diff --git a/academic/literature/index.html b/academic/literature/index.html index 941f4fbe..e3a5e30a 100644 --- a/academic/literature/index.html +++ b/academic/literature/index.html @@ -5,15 +5,15 @@ Welcome to Literature | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Welcome to Literature

Author:Anda Toshiki
Updated:4 minutes ago
Words:3
Reading:1 min
- +
Skip to content

Welcome to Literature

Author:Anda Toshiki
Updated:2 minutes ago
Words:3
Reading:1 min
+ \ No newline at end of file diff --git a/academic/literature/writing/methods-of-development.html b/academic/literature/writing/methods-of-development.html index 36b0dbd1..8b3ea60b 100644 --- a/academic/literature/writing/methods-of-development.html +++ b/academic/literature/writing/methods-of-development.html @@ -5,15 +5,15 @@ Patterns of Organization and Methods of Development | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Patterns of Organization and Methods of Development

Author:Anda Toshiki
Updated:4 minutes ago
Words:2.2k
Reading:13 min

Patterns of organization can help your readers follow the ideas within your essay and your paragraphs, but they can also work as methods of development to help you recognize and further develop ideas and relationships in your writing. Here are some strategies that can help you with both organization and development in your essays.

Major Patterns of Organization

A fruit pie.

Read the following sentences:

  • Now take the pie out of the oven and let it cool on the stovetop.
  • Mix the dry ingredients with the liquid ingredients.
  • Set the pie crust aside while you make the filling.

How did it feel to read the above list? A bit confusing, I would guess. That’s because the steps for making a pie were not well organized, and the steps don’t include enough detail for us to know exactly what we should do. (Like what are the dry and liquid ingredients?) We all know that starting instructions from the beginning and giving each detailed step in the order it should happen is vital to having a good outcome, in this case a yummy pie! But it’s not always so simple to know how to organize or develop ideas, and sometimes there’s more than one way, which complicates things even further.

First, let’s take a look at a couple of ways to think about organization.

General to Specific or Specific to General

It might be useful to think about organizing your topic like a triangle:

Two triangles. The first is an inverted pyramid for General to Specific, the second is a pyramid for Specific to General.

The first triangle represents starting with the most general, big picture information first, moving then to more detailed and often more personal information later in the paper. The second triangle represents an organizational structure that starts with the specific, small scale information first and then moves to the more global, big picture stuff.

For example, if your topic is traffic in Vancouver, British Columbia, an essay that uses the general-to-specific organizational structure might begin this way:

Many people consider Vancouver, British Columbia, to be a relaxed place to live. They would be shocked to know how bad the traffic is traveling major arteries into the city and even driving around the city itself.

An essay that uses the specific-to-general structure might start like this:

Transit is crowded, parking is expensive, and vehicles stop and go through the main streets of the city of Vancouver, British Columbia, and that is just once travelers brave the crowded arteries to enter the city; Vancouver’s traffic problem does not lend itself to the relaxed atmosphere many believe the city to have.

What’s the difference between these two introductions? And how might they appeal to the intended audience for this essay in different ways? The first introduction is looking at the big picture of the problem and mentions pollution’s impact on all citizens in Portland, while the second introduction focuses on one specific family. The first helps readers see how vast the problem really is, and the second helps connect readers to a real family, making an emotional appeal from the very beginning. Neither introduction is necessarily better. You’ll choose one over the other based on the kind of tone you’d like to create and how you’d like to affect your audience. It’s completely up to you to make this decision.

Does the Triangle Mean the Essay Keeps Getting More Specific or More Broad until the Very End?

The triangle is kind of a general guide, meaning you’re allowed to move around within it all you want. For example, it’s possible that each of your paragraphs will be its own triangle, starting with the general or specific and moving out or in. However, if you begin very broadly, it might be effective to end your essay in a more specific, personal way. And if you begin with a personal story, consider ending your essay by touching on the global impact and importance of your topic.

Are There Other Ways to Think about Organizing My Ideas?

Yes! Rather than thinking about which of your ideas are most specific or personal or which are more broad or universal, you might consider one of the following ways of organizing your ideas:

  • Most important information first (consider what you want readers to focus on first)
  • Chronological order (the order in time that events take place)
  • Compare and contrast (ideas are organized together because of their relationship to each other)

The section on Methods of Development, below, offers more detail about some of these organizational patterns, along with some others.

Choose one of the following topics, and practice writing a few opening sentences like we did above, once using the general-to-specific format and once using the specific-to-general. Which do you like better? What audience would be attracted to which one? Share with peers to see how others tackled this challenge. How would you rewrite their sentences? Why? Discuss your changes and listen to how your peers have revised your sentences. Taking in other people’s ideas will help you see new ways to approach your own writing and thinking.
Topics:

  • Facing fears
  • Safety in sports
  • Community policing
  • Educating prisoners
  • Sex education

Methods of Development

The methods of development covered here are best used as ways to look at what’s already happening in your draft and to consider how you might emphasize or expand on any existing patterns. You might already be familiar with some of these patterns because teachers will sometimes assign them as the purpose for writing an essay. For example, you might have been asked to write a cause-and-effect essay or a comparison-and-contrast essay.

It’s important to emphasize here that patterns of organization or methods of developing content usually happen naturally as a consequence of the way the writer engages with and organizes information while writing. That is to say, most writers don’t sit down and say, “I think I’ll write a cause-and-effect essay today.” Instead, a writer might be more likely to be interested in a topic, say, the state of drinking water in the local community, and as the writer begins to explore the topic, certain cause-and-effect relationships between environmental pollutants and the community water supply may begin to emerge.

So if these patterns just occur naturally in writing, what’s the use in knowing about them? Well, sometimes you might be revising a draft and notice that some of your paragraphs are a bit underdeveloped. Maybe they lack a clear topic, or maybe they lack support. In either case, you can look to these common methods of development to find ways to sharpen those vague topics or to add support where needed. Do you have a clear cause statement somewhere but you haven’t explored the effects? Are you lacking detail somewhere where a narrative story or historical chronology can help build reader interest and add support? Are you struggling to define an idea that might benefit from some comparison or contrast? Read on to consider some of the ways that these strategies can help you in revision.

Cause and Effect (or Effect and Cause)

Do you see a potential cause-and-effect relationship developing in your draft? The cause-and-effect pattern may be used to identify one or more causes followed by one or more effects or results. Or you may reverse this sequence and describe effects first and then the cause or causes. For example, the causes of water pollution might be followed by its effects on both humans and animals. You may use obvious transitions to clarify cause and effect, such as “What are the results? Here are some of them…” or you might simply use the words cause, effect, and result, to cue the reader about your about the relationships that you’re establishing.

Problem-Solution

At some point does your essay explore a problem or suggest a solution? The problem-solution pattern is commonly used in identifying something that’s wrong and in contemplating what might be done to remedy the situation. There are probably more ways to organize a problem-solution approach, but but here are three possibilities:

  • Describe the problem, followed by the solution.
  • Propose the solution first and then describe the problems that motivated it.
  • Or a problem may be followed by several solutions, one of which is selected as the best.

When the solution is stated at the end of the paper, the pattern is sometimes called the delayed proposal. For a hostile audience, it may be effective to describe the problem, show why other solutions do not work, and finally suggest the favored solution. You can emphasize the words problem and solution to signal these sections of your paper for your reader.

Chronology or Narrative

Do you need to develop support for a topic where telling a story can illustrate some important concept for your readers? Material arranged chronologically is explained as it occurs in time. A chronological or narrative method of development might help you find a way to add both interest and content to your essay. Material arranged chronologically is explained as it occurs in time. This pattern may be used to establish what has happened. Chronology or narrative can be a great way to introduce your essay by providing a background or history behind your topic. Or you may want to tell a story to develop one or more points in the body of your essay. You can use transitional words like then, next, and finally to make the parts of the chronology clear.

Comparison and Contrast

Are you trying to define something? Do you need your readers to understand what something is and what it is not? The comparison-and-contrast method of development is particularly useful in extending a definition, or anywhere you need to show how a subject is like or unlike another subject. For example, the statement is often made that drug abuse is a medical problem instead of a criminal justice issue. An author might attempt to prove this point by comparing drug addiction to AIDS, cancer, or heart disease to redefine the term “addiction” as a medical problem. A statement in opposition to this idea could just as easily establish contrast by explaining all the ways that addiction is different from what we traditionally understand as an illness. In seeking to establish comparison or contrast in your writing, some words or terms that might be useful are by contrast, in comparison, while, some, and others.

Summary

These four methods of development—cause and effect, problem-solution, chronology or narrative, and comparison and contrast—are just a few ways to organize and develop ideas and content in your essays. It’s important to note that they should not be a starting point for writers who want to write something authentic—something that they care deeply about. Instead, they can be a great way to help you look for what’s already happening with your topic or in a draft, to help you to write more, or to help you reorganize some parts of an essay that seem to lack connection or feel disjointed. Look for organizational patterns when you’re reading work by professional writers. Notice where they combine strategies (e.g., a problem-solution pattern that uses cause-and-effect organization, or a comparison-contrast pattern that uses narrative or chronology to develop similarities or differences). Pay attention to how different writers emphasize and develop their main ideas, and use what you find to inspire you in your own writing. Better yet, work on developing completely new patterns of your own.

Reference

  • This chapter was adapted from “Patterns of Organization and Methods of Development” in The Word on College Reading and Writing by Carol Burnell, Jaime Wood, Monique Babin, Susan Pesznecker, and Nicole Rosevear, which is licensed under a CC BY-NC 4.0 Licence. Adapted by Allison Kilgannon.

  • Peach and lavender pie” by Heather Joan is licensed under a CC BY-NC-ND 2.0 Licence.

  • “General to Specific vs. Specific to General Triangles” by Carol Burnell, Jaime Wood, Monique Babin, Susan Pesznecker, and Nicole Rosevear is under a CC BY-NC 4.0 Licence.

  • Kilgannon, Allison. “Patterns of Organization and Methods of Development.” Opentextbc.ca, 20 Aug. 2021, opentextbc.ca/advancedenglish/chapter/patterns-of-organization-and-methods-of-development/#:~:text=These%20four%20methods%20of%20development.

- +
Skip to content

Patterns of Organization and Methods of Development

Author:Anda Toshiki
Updated:2 minutes ago
Words:2.2k
Reading:13 min

Patterns of organization can help your readers follow the ideas within your essay and your paragraphs, but they can also work as methods of development to help you recognize and further develop ideas and relationships in your writing. Here are some strategies that can help you with both organization and development in your essays.

Major Patterns of Organization

A fruit pie.

Read the following sentences:

  • Now take the pie out of the oven and let it cool on the stovetop.
  • Mix the dry ingredients with the liquid ingredients.
  • Set the pie crust aside while you make the filling.

How did it feel to read the above list? A bit confusing, I would guess. That’s because the steps for making a pie were not well organized, and the steps don’t include enough detail for us to know exactly what we should do. (Like what are the dry and liquid ingredients?) We all know that starting instructions from the beginning and giving each detailed step in the order it should happen is vital to having a good outcome, in this case a yummy pie! But it’s not always so simple to know how to organize or develop ideas, and sometimes there’s more than one way, which complicates things even further.

First, let’s take a look at a couple of ways to think about organization.

General to Specific or Specific to General

It might be useful to think about organizing your topic like a triangle:

Two triangles. The first is an inverted pyramid for General to Specific, the second is a pyramid for Specific to General.

The first triangle represents starting with the most general, big picture information first, moving then to more detailed and often more personal information later in the paper. The second triangle represents an organizational structure that starts with the specific, small scale information first and then moves to the more global, big picture stuff.

For example, if your topic is traffic in Vancouver, British Columbia, an essay that uses the general-to-specific organizational structure might begin this way:

Many people consider Vancouver, British Columbia, to be a relaxed place to live. They would be shocked to know how bad the traffic is traveling major arteries into the city and even driving around the city itself.

An essay that uses the specific-to-general structure might start like this:

Transit is crowded, parking is expensive, and vehicles stop and go through the main streets of the city of Vancouver, British Columbia, and that is just once travelers brave the crowded arteries to enter the city; Vancouver’s traffic problem does not lend itself to the relaxed atmosphere many believe the city to have.

What’s the difference between these two introductions? And how might they appeal to the intended audience for this essay in different ways? The first introduction is looking at the big picture of the problem and mentions pollution’s impact on all citizens in Portland, while the second introduction focuses on one specific family. The first helps readers see how vast the problem really is, and the second helps connect readers to a real family, making an emotional appeal from the very beginning. Neither introduction is necessarily better. You’ll choose one over the other based on the kind of tone you’d like to create and how you’d like to affect your audience. It’s completely up to you to make this decision.

Does the Triangle Mean the Essay Keeps Getting More Specific or More Broad until the Very End?

The triangle is kind of a general guide, meaning you’re allowed to move around within it all you want. For example, it’s possible that each of your paragraphs will be its own triangle, starting with the general or specific and moving out or in. However, if you begin very broadly, it might be effective to end your essay in a more specific, personal way. And if you begin with a personal story, consider ending your essay by touching on the global impact and importance of your topic.

Are There Other Ways to Think about Organizing My Ideas?

Yes! Rather than thinking about which of your ideas are most specific or personal or which are more broad or universal, you might consider one of the following ways of organizing your ideas:

  • Most important information first (consider what you want readers to focus on first)
  • Chronological order (the order in time that events take place)
  • Compare and contrast (ideas are organized together because of their relationship to each other)

The section on Methods of Development, below, offers more detail about some of these organizational patterns, along with some others.

Choose one of the following topics, and practice writing a few opening sentences like we did above, once using the general-to-specific format and once using the specific-to-general. Which do you like better? What audience would be attracted to which one? Share with peers to see how others tackled this challenge. How would you rewrite their sentences? Why? Discuss your changes and listen to how your peers have revised your sentences. Taking in other people’s ideas will help you see new ways to approach your own writing and thinking.
Topics:

  • Facing fears
  • Safety in sports
  • Community policing
  • Educating prisoners
  • Sex education

Methods of Development

The methods of development covered here are best used as ways to look at what’s already happening in your draft and to consider how you might emphasize or expand on any existing patterns. You might already be familiar with some of these patterns because teachers will sometimes assign them as the purpose for writing an essay. For example, you might have been asked to write a cause-and-effect essay or a comparison-and-contrast essay.

It’s important to emphasize here that patterns of organization or methods of developing content usually happen naturally as a consequence of the way the writer engages with and organizes information while writing. That is to say, most writers don’t sit down and say, “I think I’ll write a cause-and-effect essay today.” Instead, a writer might be more likely to be interested in a topic, say, the state of drinking water in the local community, and as the writer begins to explore the topic, certain cause-and-effect relationships between environmental pollutants and the community water supply may begin to emerge.

So if these patterns just occur naturally in writing, what’s the use in knowing about them? Well, sometimes you might be revising a draft and notice that some of your paragraphs are a bit underdeveloped. Maybe they lack a clear topic, or maybe they lack support. In either case, you can look to these common methods of development to find ways to sharpen those vague topics or to add support where needed. Do you have a clear cause statement somewhere but you haven’t explored the effects? Are you lacking detail somewhere where a narrative story or historical chronology can help build reader interest and add support? Are you struggling to define an idea that might benefit from some comparison or contrast? Read on to consider some of the ways that these strategies can help you in revision.

Cause and Effect (or Effect and Cause)

Do you see a potential cause-and-effect relationship developing in your draft? The cause-and-effect pattern may be used to identify one or more causes followed by one or more effects or results. Or you may reverse this sequence and describe effects first and then the cause or causes. For example, the causes of water pollution might be followed by its effects on both humans and animals. You may use obvious transitions to clarify cause and effect, such as “What are the results? Here are some of them…” or you might simply use the words cause, effect, and result, to cue the reader about your about the relationships that you’re establishing.

Problem-Solution

At some point does your essay explore a problem or suggest a solution? The problem-solution pattern is commonly used in identifying something that’s wrong and in contemplating what might be done to remedy the situation. There are probably more ways to organize a problem-solution approach, but but here are three possibilities:

  • Describe the problem, followed by the solution.
  • Propose the solution first and then describe the problems that motivated it.
  • Or a problem may be followed by several solutions, one of which is selected as the best.

When the solution is stated at the end of the paper, the pattern is sometimes called the delayed proposal. For a hostile audience, it may be effective to describe the problem, show why other solutions do not work, and finally suggest the favored solution. You can emphasize the words problem and solution to signal these sections of your paper for your reader.

Chronology or Narrative

Do you need to develop support for a topic where telling a story can illustrate some important concept for your readers? Material arranged chronologically is explained as it occurs in time. A chronological or narrative method of development might help you find a way to add both interest and content to your essay. Material arranged chronologically is explained as it occurs in time. This pattern may be used to establish what has happened. Chronology or narrative can be a great way to introduce your essay by providing a background or history behind your topic. Or you may want to tell a story to develop one or more points in the body of your essay. You can use transitional words like then, next, and finally to make the parts of the chronology clear.

Comparison and Contrast

Are you trying to define something? Do you need your readers to understand what something is and what it is not? The comparison-and-contrast method of development is particularly useful in extending a definition, or anywhere you need to show how a subject is like or unlike another subject. For example, the statement is often made that drug abuse is a medical problem instead of a criminal justice issue. An author might attempt to prove this point by comparing drug addiction to AIDS, cancer, or heart disease to redefine the term “addiction” as a medical problem. A statement in opposition to this idea could just as easily establish contrast by explaining all the ways that addiction is different from what we traditionally understand as an illness. In seeking to establish comparison or contrast in your writing, some words or terms that might be useful are by contrast, in comparison, while, some, and others.

Summary

These four methods of development—cause and effect, problem-solution, chronology or narrative, and comparison and contrast—are just a few ways to organize and develop ideas and content in your essays. It’s important to note that they should not be a starting point for writers who want to write something authentic—something that they care deeply about. Instead, they can be a great way to help you look for what’s already happening with your topic or in a draft, to help you to write more, or to help you reorganize some parts of an essay that seem to lack connection or feel disjointed. Look for organizational patterns when you’re reading work by professional writers. Notice where they combine strategies (e.g., a problem-solution pattern that uses cause-and-effect organization, or a comparison-contrast pattern that uses narrative or chronology to develop similarities or differences). Pay attention to how different writers emphasize and develop their main ideas, and use what you find to inspire you in your own writing. Better yet, work on developing completely new patterns of your own.

Reference

  • This chapter was adapted from “Patterns of Organization and Methods of Development” in The Word on College Reading and Writing by Carol Burnell, Jaime Wood, Monique Babin, Susan Pesznecker, and Nicole Rosevear, which is licensed under a CC BY-NC 4.0 Licence. Adapted by Allison Kilgannon.

  • Peach and lavender pie” by Heather Joan is licensed under a CC BY-NC-ND 2.0 Licence.

  • “General to Specific vs. Specific to General Triangles” by Carol Burnell, Jaime Wood, Monique Babin, Susan Pesznecker, and Nicole Rosevear is under a CC BY-NC 4.0 Licence.

  • Kilgannon, Allison. “Patterns of Organization and Methods of Development.” Opentextbc.ca, 20 Aug. 2021, opentextbc.ca/advancedenglish/chapter/patterns-of-organization-and-methods-of-development/#:~:text=These%20four%20methods%20of%20development.

+ \ No newline at end of file diff --git a/academic/physics/index.html b/academic/physics/index.html index 6f3f0e45..722dbdd1 100644 --- a/academic/physics/index.html +++ b/academic/physics/index.html @@ -5,15 +5,15 @@ Welcome to Physics | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Welcome to Physics

Author:Anda Toshiki
Updated:4 minutes ago
Words:3
Reading:1 min
- +
Skip to content

Welcome to Physics

Author:Anda Toshiki
Updated:2 minutes ago
Words:3
Reading:1 min
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/1.html b/academic/physics/ipho-formulas-jpn/1.html index 86e49d6e..b16c23b6 100644 --- a/academic/physics/ipho-formulas-jpn/1.html +++ b/academic/physics/ipho-formulas-jpn/1.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 1 | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 1

Author:Anda Toshiki
Updated:4 minutes ago
Words:1.1k
Reading:5 min

1: 数学

1.1: Taylor 展開

  1. Taylor 展開(アバウトに切り捨てる:

    F(x)=F(x0)+F(n)(x0)(xx0)n/nF(x)=F\left(x_{0}\right)+\sum F^{(n)}\left(x_{0}\right)\left(x-x_{0}\right)^{n} / n

    線形近似(特別な場合):

    F(x)F(x0)+F(x0)(xx0)F(x) \approx F\left(x_{0}\right)+F^{\prime}\left(x_{0}\right)\left(x-x_{0}\right)

    x1|x| \ll 1 のときの例 ::

    sinxx,cosx1x2/2,ex1+x\sin x \approx x, \cos x \approx 1-x^{2} / 2, e^{x} \approx 1+x

    ln(1+x)x,(1+x)n1+nx\ln (1+x) \approx x,(1+x)^{n} \approx 1+n x

1.2: 摂動法

  1. 摂動法:摂動のない(直接解ける)問題の解を 00 番目の近似値として求め,前の似値に基づく次の近似値の補正を繰り返して解を求める.

1.3: 定数係数線形微分方程式

  1. 定数係数線形微分方程式 ay+by+cy=0a y^{\prime \prime}+b y^{\prime}+c y=0 の解:

    y=Aexp(λ1x)+Bexp(λ2x)y=A \exp \left(\lambda_1 x\right)+B \exp \left(\lambda_2 x\right) \text {. }

    ここで λ1,2\lambda_{1,2} は特性方程式 aλ2+bλ+c=0a \lambda^2+b \lambda+c=0 の異な る 2 解. もし a,b,ca, b, c が実数で特性方程式の解が複素数 λ1,2=γ±iω\lambda_{1,2}=\gamma \pm i \omega ならば,

    y=Ceγxsin(ωx+φ0)y=C e^{\gamma x} \sin \left(\omega x+\varphi_0\right)

1.4: 複素数

  1. 複素数

    z=a+bi=zeiφ,zˉ=abi=zeiφz2=zzˉ=a2+b2,φ=argz=arcsinbzRez=(z+zˉ)/2,Imz=(zzˉ)/2iz1z2=z1z2,argz1z2=argz1+argz2eiφ=cosφ+isinφcosφ=eiφ+eiφ2,sinφ=eiφeiφ2i\begin{gathered} z=a+b i=|z| e^{i \varphi}, \bar{z}=a-b i=|z| e^{-i \varphi} \\ |z|^2=z \bar{z}=a^2+b^2, \varphi=\arg z=\arcsin \frac{b}{|z|} \\ \operatorname{Re} z=(z+\bar{z}) / 2, \operatorname{Im} z=(z-\bar{z}) / 2 i \\ \left|z_1 z_2\right|=\left|z_1\right|\left|z_2\right|, \arg z_1 z_2=\arg z_1+\arg z_2 \\ e^{i \varphi}=\cos \varphi+i \sin \varphi \\ \cos \varphi=\frac{e^{i \varphi}+e^{-i \varphi}}{2}, \sin \varphi=\frac{e^{i \varphi}-e^{-i \varphi}}{2 i} \end{gathered}

1.5: ベクトルの内積と外積

  1. ベクトルの内積と外積は分配法則が成立する : a(b+c)=ab+aca(b+c)=a b+a c

    ab=ba=axbx+ayby+=abcosφa×b=absinφ,a×b=b×aa,ba×b=(aybzazby)ex+(azbxaxbz)ey+a×[b×c]=(ac)b(ab)c\begin{gathered} \boldsymbol{a} \cdot \boldsymbol{b}=\boldsymbol{b} \cdot \boldsymbol{a}=a_x b_x+a_y b_y+\cdots=a b \cos \varphi \\ |\boldsymbol{a} \times \boldsymbol{b}|=a b \sin \varphi, \boldsymbol{a} \times \boldsymbol{b}=-\boldsymbol{b} \times \boldsymbol{a} \perp \boldsymbol{a}, \boldsymbol{b} \\ \boldsymbol{a} \times \boldsymbol{b}=\left(a_y b_z-a_z b_y\right) \boldsymbol{e}_x+\left(a_z b_x-a_x b_z\right) \boldsymbol{e}_y+\cdots \\ \boldsymbol{a} \times[\boldsymbol{b} \times \boldsymbol{c}]=(\boldsymbol{a} \cdot \boldsymbol{c}) \boldsymbol{b}-(\boldsymbol{a} \cdot \boldsymbol{b}) \boldsymbol{c} \end{gathered}

    スカラー三重積(3 つのベクトルで張られる平行四面 体の体積):

    (a,b,c)a[b×c]=[a×b]c=(b,c,a)(\boldsymbol{a}, \boldsymbol{b}, \boldsymbol{c}) \equiv \boldsymbol{a} \cdot[\boldsymbol{b} \times \boldsymbol{c}]=[\boldsymbol{a} \times \boldsymbol{b}] \cdot \boldsymbol{c}=(\boldsymbol{b}, \boldsymbol{c}, \boldsymbol{a})

1.6: 余弦定理と正弦定理

  1. 余弦定理と正弦定理:

    c2=a2+b22abcosCa/sinA=b/sinB=2R\begin{aligned} & c^2=a^2+b^2-2 a b \cos C \\ & a / \sin A=b / \sin B=2 R \end{aligned}

1.7: 三角法

  1. sin(α±β)=sinαcosβ±cosαsinβcos(α±β)=cosαcosβsinαsinβtan(α±β)=(tanα±tanβ)/(1tanαtanβ)cos2α=1+cos2α2,sin2α=1cos2α2cosαcosβ=cos(α+β)+cos(αβ)2,cosα+cosβ=2(cosα+β2+cosαβ2),\begin{aligned} & \sin (\alpha \pm \beta)=\sin \alpha \cos \beta \pm \cos \alpha \sin \beta \\ & \cos (\alpha \pm \beta)=\cos \alpha \cos \beta \mp \sin \alpha \sin \beta \\ & \tan (\alpha \pm \beta)=(\tan \alpha \pm \tan \beta) /(1 \mp \tan \alpha \tan \beta) \\ & \cos ^2 \alpha=\frac{1+\cos 2 \alpha}{2}, \sin ^2 \alpha=\frac{1-\cos 2 \alpha}{2} \\ & \cos \alpha \cos \beta=\frac{\cos (\alpha+\beta)+\cos (\alpha-\beta)}{2}, \ldots \\ & \cos \alpha+\cos \beta=2\left(\cos \frac{\alpha+\beta}{2}+\cos \frac{\alpha-\beta}{2}\right), \ldots \end{aligned}

1.8: 円周角

  1. 円周角は中心角の半分. よって,直角三角形の斜辺は その外接円の直径. もし四角形の対角の和が 180 度な らば,それは円に内接する.

1.9: 三角形の面樍

  1. 三角形の面樍 =12aha=pr=p(pa)(pb)(pc)=abc/4R=\frac{1}{2} a h_a=p r=\sqrt{p(p-a)(p-b)(p-c)}=a b c / 4 R
- +M1001 80h400000v40h-400000z">

1.13: 積分

  1. 積分:微分の公式の左辺と右辺を入れ替えたものと同 じ(逆演算).例えば,

    xn dx=xn+1/(n+1).\int x^n \mathrm{~d} x=x^{n+1} /(n+1) .

    置換積分の特別な場合 :

    f(ax+b)dx=F(ax+b)/a.\int f(a x+b) \mathrm{d} x=F(a x+b) / a .

1.14: 円錐曲線

  1. 円錐曲線: a11x2+2a12xy+a22y2+a1x+a2y+a0=a_{11} x^2+2 a_{12} x y+a_{22} y^2+a_1 x+a_2 y+a_0= 0 で, a11=a22a_{11}=a_{22} ならば円, a11(a11a22a122)>0a_{11}\left(a_{11} a_{22}-a_{12}^2\right)>0 ならば楕円, <0\cdots<0 ならば双曲線, a11a22a122=0a_{11} a_{22}-a_{12}^2=0 ならば放物線. 楕円 : l1+l2=2a,α1=α2l_1+l_2=2 a, \alpha_1=\alpha_2 [訳 者注 : 焦点と曲線上の点を結ぶ直線と接線とのなす角 ], A=πabA=\pi a b. 双曲線 : l1l2=2a,α1+α2=0l_1-l_2=2 a, \alpha_1+\alpha_2=0. 放物線 :l+h=: l+h= const., α1=α2\alpha_1=\alpha_2.

1.15: 数值計算 & 台形規則

  1. 数值計算. f(x)=0f(x)=0 の解を求めるニュートン法 :

    xn+1=xnf(xn)/f(xn)x_{n+1}=x_n-f\left(x_n\right) / f^{\prime}\left(x_n\right)

    近似積分の台形規則:

    abf(x)dxba2n[f(x0)+2{f(x1)++f(xn1)}+f(xn)]\begin{array}{r} \int_a^b f(x) \mathrm{d} x \approx \frac{b-a}{2 n}\left[f\left(x_0\right)+2\left\{f\left(x_1\right)+\cdots\right.\right. \left.\left.+f\left(x_{n-1}\right)\right\}+f\left(x_n\right)\right] \end{array}

1.16: ベクトルの微分 & 積分

  1. ベクトルの微分と積分:成分ごとに微分/積分する.あるいは無限に近い22つのベクトルの差を求めることで 微分す.
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/10.html b/academic/physics/ipho-formulas-jpn/10.html index 09a90b8a..275ff9b4 100644 --- a/academic/physics/ipho-formulas-jpn/10.html +++ b/academic/physics/ipho-formulas-jpn/10.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 10 | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 10

Author:Anda Toshiki
Updated:4 minutes ago
Words:613
Reading:3 min

10: 熱力学

10.1: pV=wMRTp V=\frac{w}{M} R T

  1. pV=wMRTp V=\frac{w}{M} R T.

10.2: モルの気体の内部エネルギー

  1. 1 モルの気体の内部エネルギー: U=i2RTU=\frac{i}{2} R T [訳者注: 単 原子分子理想気体 i=3i=3, 二原子分子理想気体 i=5]i=5].

10.3: 標準状態

  1. 標準状態での 1 モルの気体の体積は 22.4 L22.4 \mathrm{~L}.

10.4: 断熱過程

  1. 断熱過程: 音速に比べて遅く, 熱の出入りがない. pVγ=p V^\gamma= const. (TVγ1=\left(T V^{\gamma-1}=\right. const. )).

10.5: γ=Cp/Cv=(i+2)/i

  1. γ=cp/cv=(i+2)/i\gamma=c_p / c_v=(i+2) / i.

10.6: Boltzmann 分布

  1. Boltzmann 分布 :

    ρ=ρ0eMgh/RT=ρ0eU/kBT\rho=\rho_0 e^{-M g h / R T}=\rho_0 e^{-U / k_B T}

10.7: Maxwell 分布

  1. Maxwell 分布(v の速さをもつ分子の数)

    訳者注

    位相空間で v\boldsymbol{v}v+dv\boldsymbol{v}+\mathrm{d} \boldsymbol{v} の間にある分子の数の分布 であり,v の速さをもつ分子の数の分布とは異なる] emv2/2kBT\propto e^{-m \boldsymbol{v}^2 / 2 k_B T}

10.8: 大気圧

  1. 大気圧 : Δpp\Delta p \ll p ならば Δp=ρgΔh\Delta p=\rho g \Delta h.

10.9: 公式

  1. p=13mnv2=nkBT(np=\frac{1}{3} m n \overline{v^2}=n k_B T(n は数密度 ),v2=), \sqrt{\overline{\overline{v^2}}}=
- +M1001 80h400000v40h-400000z">,ν=vnS.

10.10: Carnot サイクル

  1. Carnot サイクル : 断熱過程 2 つと等温過程 2 つ. STS-T 座標を用いることにより η=(T1T2)/T1\eta=\left(T_1-T_2\right) / T_1 を得る.

10.11: ヒートポンプ

  1. ヒートポンプ: Carnot サイクルの逆. η=T1T1T2\eta=\frac{T_1}{T_1-T_2}.

10.12: エントロピー

  1. エントロピー :dS=dQ/T: \mathrm{d} S=\mathrm{d} Q / T.

10.13: 熱力学第一法則

  1. 熱力学第一法則 : dU=dA+dQ\mathrm{d}^{\prime} U=\mathrm{d}^{\prime} A+\mathrm{d}^{\prime} Q

10.14: 熱力学第二法則

  1. 熱力学第二法則 : ΔS0\Delta S \geq 0 (また ηreal ηCarnot )\left.\eta_{\text {real }} \leq \eta_{\text {Carnot }}\right).

10.15: 気体のする仕事

  1. 気体のする仕事(ポイント 10 も参照):

    A=p dV, 断熱過程: A=i2Δ(pV)A=\int p \mathrm{~d} V, \quad \text { 断熱過程: } A=\frac{i}{2} \Delta(p V)

10.16: Dalton の法則

  1. Dalton の法則: p=p= pi\sum p_i

    訳者注

    理想気体のみ成立

10.17: 沸騰

  1. 沸騰: 飽和蒸気の圧力 pv=p0.2p_v=p_0 .2 液の界面では pv1+pv2=p0p_{v 1}+p_{v 2}=p_0.

10.18: 熱流

  1. 熱流: P=kSΔT/lP=k S \Delta T / l ( kk は熱伝導率). 直流回路に似て いる (PI,ΔTV,k1/ρ)(P \leftrightarrow I, \Delta T \leftrightarrow V, k \leftrightarrow 1 / \rho).

10.19: 熱容量

  1. 熱容量 : Q=c(T)dTQ=\int c(T) \mathrm{d} T. 固体では低温で cT3c \propto T^3, 高温で c=3NkBc=3 N k_B (Dulong-Petit の法則. ここで NN は結晶中の原子数)

10.20: 表面張力

  1. 表面張力 :

    U=Sσ,F=lσ,p=2σ/RU=S \sigma, F=l \sigma, p=2 \sigma / R

10.21: Stefan-Boltzmann の法則 (灰色体)

  1. Stefan-Boltzmann の法則 (灰色体) : P=εσAT4P=\varepsilon \sigma A T^4.

10.22: Wien の変位則

  1. Wien の変位則: νmax=AkBT/h(A\nu_{\max }=A k_B T / h(A \approx 2.8), λmax=hc/AkBT(A5)\lambda_{\max }=h c / A^{\prime} k_B T\left(A^{\prime} \approx 5\right).
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/11.html b/academic/physics/ipho-formulas-jpn/11.html index 0ec2b230..3665c3db 100644 --- a/academic/physics/ipho-formulas-jpn/11.html +++ b/academic/physics/ipho-formulas-jpn/11.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 11 | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 11

Author:Anda Toshiki
Updated:4 minutes ago
Words:314
Reading:1 min

11: 量子力学

11.1:p=hk

  1. p=k(p=h/λ),E=ω=hν\boldsymbol{p}=\hbar \boldsymbol{k}(|\boldsymbol{p}|=h / \lambda), E=\hbar \omega=h \nu.

11.2: 干渉

  1. 干渉 : 波動光学のように.

11.3: 不確定性

  1. 不確定性(数学の定理):

    ΔpΔx2,ΔEΔt2,ΔωΔt12\Delta p \Delta x \geq \frac{\hbar}{2}, \Delta E \Delta t \geq \frac{\hbar}{2}, \Delta \omega \Delta t \geq \frac{1}{2}

    滑らかでない場合の定性的な推定には hh の方が適する (ΔpΔxh(\Delta p \Delta x \approx h など )).

11.4: スペクトル

  1. スペクトル : hν=EnEmh \nu=E_n-E_m. スペクトル線の幅は寿 命に関係し, Γτ\Gamma \tau \approx \hbar.

11.5: 振動子

  1. 振動子(例えば分子)のエネルギー準位(固有振動数 ν0):En=(n+12)hν0\left.\nu_0\right): E_n=\left(n+\frac{1}{2}\right) h \nu_0. 多数の固有振動数の場合, E=hniνiE=\sum h n_i \nu_i.

11.6: トンネル効果

  1. トンネル効果: 幅 ll の障壁 Γ\Gamma は, Γτ(τ=\Gamma \tau \approx \hbar(\tau= l/Γ/m)l / \sqrt{\Gamma / m})
- +M1001 80h400000v40h-400000z">) であれば容易に透過する.

11.7: Bohr モデル

  1. Bohr モデル : En1/n2E_n \propto-1 / n^2. (古典的に計算される) 円軌道では, 軌道の長さが波長 λ=h/mv\lambda=h / m v の整数倍.

11.8: Compton 効果

  1. Compton 効果: 光子が電子から散乱されると, 光子の Δλ=λC(1cosθ)\Delta \lambda=\lambda_C(1-\cos \theta)

11.9: 光電効果

  1. 光電効果: W+mvmax2/2=hνW+m v_{\max }^2 / 2=h \nu ( WW は仕事関数 )). IVI-V グラフ:光電流は阻止電圧 V=(hνW)/eV=-(h \nu-W) / e で始まり, 正方向に電圧が大きくなると緩和する.

11.10: Stefan-Boltzmann の法則

  1. Stefan-Boltzmann の法則 : P=σAT4P=\sigma A T^4
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/12.html b/academic/physics/ipho-formulas-jpn/12.html index 837288d9..77efb41b 100644 --- a/academic/physics/ipho-formulas-jpn/12.html +++ b/academic/physics/ipho-formulas-jpn/12.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 12 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 12

Author:Anda Toshiki
Updated:4 minutes ago
Words:332
Reading:1 min

12: Kepler の法則

12.1: F & U

  1. F=GMm/r2,U=GMm/rF=G M m / r^2, U=-G M m / r \text {. }

12.2: Kepler の第一法則

  1. Kepler の第一法則 (2 質点の重力相互作用):それぞ れの軌道は,系の質量中心に焦点を持つ楕円,双曲線, 放物線になる. これは Runge-Lenz ベクトルから得ら れる (ポイント 9).

12.3: Kepler の第二法則

  1. Kepler の第二法則(角運動量の保存): 中心力が働く 場にある質点について,その位置ベクトルは単位時間 に一定の面積を描く.

12.4: Kepler の第三法則

  1. Kepler の第三法則 :r2: r^{-2} に比例する力が働く場で楕円 軌道を描く複数の質点について, 周期は長半径の 32\frac{3}{2} 乗 に比例する :

    T12/T22=a13/a23T_1^2 / T_2^2=a_1^3 / a_2^3

12.5: 楕円軌道

  1. 重力場中で楕円軌道を描く質点の全エネルギー (K+U)(K+U) :

    E=GMm/2aE=-G M m / 2 a

12.6: 楕円率

  1. 楕円率が ε=d/a1\varepsilon=d / a \ll 1 の場合, 軌道は焦点をずらし た円形をしていると考えられる.

12.7: 楕円の性質

  1. 楕円の性質 :l1+l2=2al1: l_1+l_2=2 a ( l_1l2l_2 は焦点までの距 離). α1=α2\alpha_1=\alpha_2 (一方の焦点から出た光は他方の焦点に 反射する). S=πabS=\pi a b.

12.8: 円の中心

  1. 円とその円の中心に焦点をもつ楕円は長軸の部分での み接する.

12.9: nge-Lenz ベクトル

  1. Runge-Lenz ベクトル(楕円率ベクトル)[訳者注:こ のベクトルはむしろ離心率と関係する.そこでここで は離心率ベクトルとして知られるベクトルを代わりに 記す.これは焦点から近日点に向かう向きで,大きさ が離心率 ee に一致する.]:

    e=v×MGMmer= const. \boldsymbol{e}=\frac{\boldsymbol{v} \times \boldsymbol{M}}{G M m}-\boldsymbol{e}_r=\text { const. }

- +
Skip to content

Formulas for IPhO 日本語版: Section 12

Author:Anda Toshiki
Updated:2 minutes ago
Words:332
Reading:1 min

12: Kepler の法則

12.1: F & U

  1. F=GMm/r2,U=GMm/rF=G M m / r^2, U=-G M m / r \text {. }

12.2: Kepler の第一法則

  1. Kepler の第一法則 (2 質点の重力相互作用):それぞ れの軌道は,系の質量中心に焦点を持つ楕円,双曲線, 放物線になる. これは Runge-Lenz ベクトルから得ら れる (ポイント 9).

12.3: Kepler の第二法則

  1. Kepler の第二法則(角運動量の保存): 中心力が働く 場にある質点について,その位置ベクトルは単位時間 に一定の面積を描く.

12.4: Kepler の第三法則

  1. Kepler の第三法則 :r2: r^{-2} に比例する力が働く場で楕円 軌道を描く複数の質点について, 周期は長半径の 32\frac{3}{2} 乗 に比例する :

    T12/T22=a13/a23T_1^2 / T_2^2=a_1^3 / a_2^3

12.5: 楕円軌道

  1. 重力場中で楕円軌道を描く質点の全エネルギー (K+U)(K+U) :

    E=GMm/2aE=-G M m / 2 a

12.6: 楕円率

  1. 楕円率が ε=d/a1\varepsilon=d / a \ll 1 の場合, 軌道は焦点をずらし た円形をしていると考えられる.

12.7: 楕円の性質

  1. 楕円の性質 :l1+l2=2al1: l_1+l_2=2 a ( l_1l2l_2 は焦点までの距 離). α1=α2\alpha_1=\alpha_2 (一方の焦点から出た光は他方の焦点に 反射する). S=πabS=\pi a b.

12.8: 円の中心

  1. 円とその円の中心に焦点をもつ楕円は長軸の部分での み接する.

12.9: nge-Lenz ベクトル

  1. Runge-Lenz ベクトル(楕円率ベクトル)[訳者注:こ のベクトルはむしろ離心率と関係する.そこでここで は離心率ベクトルとして知られるベクトルを代わりに 記す.これは焦点から近日点に向かう向きで,大きさ が離心率 ee に一致する.]:

    e=v×MGMmer= const. \boldsymbol{e}=\frac{\boldsymbol{v} \times \boldsymbol{M}}{G M m}-\boldsymbol{e}_r=\text { const. }

+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/13.html b/academic/physics/ipho-formulas-jpn/13.html index a0dcd250..07a000a0 100644 --- a/academic/physics/ipho-formulas-jpn/13.html +++ b/academic/physics/ipho-formulas-jpn/13.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 13 | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 13

Author:Anda Toshiki
Updated:4 minutes ago
Words:488
Reading:2 min

13: 相対性理論

13.1:Lorentz 変換

  1. Lorentz 変換 (Minkowski 幾何学の 4 次元時空の回 転)(慣性系間の速度が V=Vex):β=V/c,γ=\left.\boldsymbol{V}=V \boldsymbol{e}_x\right): \beta=V / c, \gamma=

    1/1β2 として, ct=γ(ctβx),x=γ(xβct),y=yE/c=γ(E/cβpx),px=γ(pxβE/c),py=py ここで, E=mc21v2/c2=mc2+12mv2+px=mvx1v2/c2, etc. \begin{aligned} & 1 / \sqrt{1-\beta^2} \text { として, } \\ & \qquad c t^{\prime}=\gamma(c t-\beta x), x^{\prime}=\gamma(x-\beta c t), y^{\prime}=y \\ & E^{\prime} / c=\gamma\left(E / c-\beta p_x\right), p_x^{\prime}=\gamma\left(p_x-\beta E / c\right), p_y^{\prime}=p_y \\ & \text { ここで, } \\ & E=\frac{m c^2}{\sqrt{1-v^2 / c^2}}=m c^2+\frac{1}{2} m v^2+\cdots \\ & p_x=\frac{m v_x}{\sqrt{1-v^2 / c^2}}, \text { etc. } \end{aligned}

    Skip to content

    Formulas for IPhO 日本語版: Section 13

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:488
    Reading:2 min

    13: 相対性理論

    13.1:Lorentz 変換

    1. Lorentz 変換 (Minkowski 幾何学の 4 次元時空の回 転)(慣性系間の速度が V=Vex):β=V/c,γ=\left.\boldsymbol{V}=V \boldsymbol{e}_x\right): \beta=V / c, \gamma=

      1/1β2 として, ct=γ(ctβx),x=γ(xβct),y=yE/c=γ(E/cβpx),px=γ(pxβE/c),py=py ここで, E=mc21v2/c2=mc2+12mv2+px=mvx1v2/c2, etc. \begin{aligned} & 1 / \sqrt{1-\beta^2} \text { として, } \\ & \qquad c t^{\prime}=\gamma(c t-\beta x), x^{\prime}=\gamma(x-\beta c t), y^{\prime}=y \\ & E^{\prime} / c=\gamma\left(E / c-\beta p_x\right), p_x^{\prime}=\gamma\left(p_x-\beta E / c\right), p_y^{\prime}=p_y \\ & \text { ここで, } \\ & E=\frac{m c^2}{\sqrt{1-v^2 / c^2}}=m c^2+\frac{1}{2} m v^2+\cdots \\ & p_x=\frac{m v_x}{\sqrt{1-v^2 / c^2}}, \text { etc. } \end{aligned}

    13.11: 電場と磁場の Lorentz 変換

    1. 電場と磁場の Lorentz 変換 : E=E,B=B\boldsymbol{E}_{\|}^{\prime}=\boldsymbol{E}_{\|}, \boldsymbol{B}_{\|}^{\prime}=\boldsymbol{B}_{\|},

      E/c=γ(E/c+v/c×B),B=γ(Bv/c×E/c)\begin{gathered} \boldsymbol{E}_{\perp}^{\prime} / c=\gamma\left(\boldsymbol{E}_{\perp} / c+\boldsymbol{v} / c \times \boldsymbol{B}_{\perp}\right), \\ \boldsymbol{B}_{\perp}^{\prime}=\gamma\left(\boldsymbol{B}_{\perp}-\boldsymbol{v} / c \times \boldsymbol{E}_{\perp} / c\right) \end{gathered}

- +M1001 80h400000v40h-400000z">

13.11: 電場と磁場の Lorentz 変換

  1. 電場と磁場の Lorentz 変換 : E=E,B=B\boldsymbol{E}_{\|}^{\prime}=\boldsymbol{E}_{\|}, \boldsymbol{B}_{\|}^{\prime}=\boldsymbol{B}_{\|},

    E/c=γ(E/c+v/c×B),B=γ(Bv/c×E/c)\begin{gathered} \boldsymbol{E}_{\perp}^{\prime} / c=\gamma\left(\boldsymbol{E}_{\perp} / c+\boldsymbol{v} / c \times \boldsymbol{B}_{\perp}\right), \\ \boldsymbol{B}_{\perp}^{\prime}=\gamma\left(\boldsymbol{B}_{\perp}-\boldsymbol{v} / c \times \boldsymbol{E}_{\perp} / c\right) \end{gathered}

+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/2.html b/academic/physics/ipho-formulas-jpn/2.html index 523832fa..0fd18e4c 100644 --- a/academic/physics/ipho-formulas-jpn/2.html +++ b/academic/physics/ipho-formulas-jpn/2.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 2 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 2

Author:Anda Toshiki
Updated:4 minutes ago
Words:210
Reading:1 min

2: 一般的な推奨事

  1. 全ての計算式の正しさを確かめる:a) 次元を調べる. b) 簡単で特別な場合を調べる(2 つの変数が等しい, 1 つの変数が 0 または \infty ). c) 解の定性的な挙動の妥当 性を調ベる. 2.もし問題文中に驚くベき偶然の一致があれば(例えば 2 つのものが同じ), 解答の鍵はそこにあるかもしれ ない.
  2. 問題文中の推奨事項をよく読む. 些細な部分に重要な 情報が含まれている場合があるので,問題文の文言に 注意する. かなり時間をかけても問題が解けない場合 は, 問題を誤解しているかもしれないので, もう一度 問題文を読む.
  3. 長くて時間のかかる計算は, 簡略化しなければならな い始めの方程式を全て書き出したのち, 最後(他の全 てが終わったとき) まで先送りする.
  4. 絶望的に難しいと思われる問題でも,たいてい非常に シンプルな解法がある.オリンピックの問題に限って 言えば,絶対に解ける.
  5. 実験では, a) 測定するほどの時問が無いとしても, 実 験計画の概略を書く,b) 結果の正確さを高める方法を 考える,c) 測定した值を全て(表として)書き出す.
- +
Skip to content

Formulas for IPhO 日本語版: Section 2

Author:Anda Toshiki
Updated:2 minutes ago
Words:210
Reading:1 min

2: 一般的な推奨事

  1. 全ての計算式の正しさを確かめる:a) 次元を調べる. b) 簡単で特別な場合を調べる(2 つの変数が等しい, 1 つの変数が 0 または \infty ). c) 解の定性的な挙動の妥当 性を調ベる. 2.もし問題文中に驚くベき偶然の一致があれば(例えば 2 つのものが同じ), 解答の鍵はそこにあるかもしれ ない.
  2. 問題文中の推奨事項をよく読む. 些細な部分に重要な 情報が含まれている場合があるので,問題文の文言に 注意する. かなり時間をかけても問題が解けない場合 は, 問題を誤解しているかもしれないので, もう一度 問題文を読む.
  3. 長くて時間のかかる計算は, 簡略化しなければならな い始めの方程式を全て書き出したのち, 最後(他の全 てが終わったとき) まで先送りする.
  4. 絶望的に難しいと思われる問題でも,たいてい非常に シンプルな解法がある.オリンピックの問題に限って 言えば,絶対に解ける.
  5. 実験では, a) 測定するほどの時問が無いとしても, 実 験計画の概略を書く,b) 結果の正確さを高める方法を 考える,c) 測定した值を全て(表として)書き出す.
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/3.html b/academic/physics/ipho-formulas-jpn/3.html index 7e14674e..8afc5068 100644 --- a/academic/physics/ipho-formulas-jpn/3.html +++ b/academic/physics/ipho-formulas-jpn/3.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 3 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 3

Author:Anda Toshiki
Updated:4 minutes ago
Words:473
Reading:2 min

3: 運動学

3.1: 質点

  1. 質点または剛体の並進運動の場合(積分 → グラフの下 の面積):

    v=dxdt,x=vdt(x=vx dt など )a=dvdt=d2xdt2,v=adtt=vx1 dx=ax1 dvx,x=vxax dvx\begin{gathered} \boldsymbol{v}=\frac{\mathrm{d} \boldsymbol{x}}{\mathrm{d} t}, \boldsymbol{x}=\int \boldsymbol{v} \mathrm{d} t\left(x=\int v_x \mathrm{~d} t \text { など }\right) \\ \boldsymbol{a}=\frac{\mathrm{d} \boldsymbol{v}}{\mathrm{d} t}=\frac{\mathrm{d}^2 \boldsymbol{x}}{\mathrm{d} t^2}, \boldsymbol{v}=\int \boldsymbol{a} \mathrm{d} t \\ t=\int v_x^{-1} \mathrm{~d} x=\int a_x^{-1} \mathrm{~d} v_x, x=\int \frac{v_x}{a_x} \mathrm{~d} v_x \end{gathered}

    もし aa が定数ならば, これらの積分は簡単に求めるこ とができて, 例えば

    x=v0t+at2/2=(v2v02)/2ax=v_0 t+a t^2 / 2=\left(v^2-v_0^2\right) / 2 a \text {. }

3.2: 回転運動

  1. 回転運動は, 並進運動と似ていて:

    ω=dφ/dt,ε=dω/dta=τdv/dt+nv2/R\begin{aligned} \omega & =\mathrm{d} \varphi / \mathrm{d} t, \varepsilon=\mathrm{d} \omega / \mathrm{d} t \\ \boldsymbol{a} & =\boldsymbol{\tau} \mathrm{d} v / \mathrm{d} t+\boldsymbol{n} v^2 / R \end{aligned}

3.3: 曲線運動

  1. 曲線運動は,ポイント 1 と同じだが,ベクトルは線速 度,加速度,経路長に置き換える.

3.4: 剛体の運動

  1. 剛体の運動:
    • vAcosα=vBcosβv_A \cos \alpha=v_B \cos \beta ここで, vA\boldsymbol{v}_AvB\boldsymbol{v}_B は剛体上の点 AABB の速度, α\alphaβ\betavA\boldsymbol{v}_AvB\boldsymbol{v}_B が直線 ABA B となす角.
    • 瞬間回転中心 (#質点の軌道 の曲率中心)は, a\boldsymbol{a}b\boldsymbol{b} に下ろした垂線の交点. 又は もし vA,vBAB\boldsymbol{v}_A, \boldsymbol{v}_B \perp A B ならば, vA\boldsymbol{v}_AvB\boldsymbol{v}_B の先端を結ぶ 直線と ABA B の交点.

3.5: 非慣性系

  1. 非慣性系:

    v2=v0+v1,a2=a0+a1+ω2R+aCor ここで, aCorv1. もし v1=0 なら aCor=0.\begin{array}{r} \quad \boldsymbol{v}_2=\boldsymbol{v}_0+\boldsymbol{v}_1, \boldsymbol{a}_2=\boldsymbol{a}_0+\boldsymbol{a}_1+\omega^2 \boldsymbol{R}+\boldsymbol{a}_{C o r} \\ \text { ここで, } \boldsymbol{a}_{C o r} \perp \boldsymbol{v}_1 . \text { もし } \boldsymbol{v}_1=0 \text { なら } \boldsymbol{a}_{C o r}=0 . \end{array}

3.6: 弾道問題

  1. 弾道問題:到達可能な範囲は

    yv02/(2g)gx2/(2v02)y \leq v_0^2 /(2 g)-g x^2 /\left(2 v_0^2\right)

    最適な弾道では, 初速度と終速(衝突時の速度)が垂直 になる.

3.7: 最短経路

  1. 最短経路を求めるには,Fermat と Huygens の原理が 使える.

3.8: ベクトル

  1. ベクトル(速度,加速度)を求めるには,その向きと (場合によっては傾いた)ある軸への射影を求めれば 充分.
- +
Skip to content

Formulas for IPhO 日本語版: Section 3

Author:Anda Toshiki
Updated:2 minutes ago
Words:473
Reading:2 min

3: 運動学

3.1: 質点

  1. 質点または剛体の並進運動の場合(積分 → グラフの下 の面積):

    v=dxdt,x=vdt(x=vx dt など )a=dvdt=d2xdt2,v=adtt=vx1 dx=ax1 dvx,x=vxax dvx\begin{gathered} \boldsymbol{v}=\frac{\mathrm{d} \boldsymbol{x}}{\mathrm{d} t}, \boldsymbol{x}=\int \boldsymbol{v} \mathrm{d} t\left(x=\int v_x \mathrm{~d} t \text { など }\right) \\ \boldsymbol{a}=\frac{\mathrm{d} \boldsymbol{v}}{\mathrm{d} t}=\frac{\mathrm{d}^2 \boldsymbol{x}}{\mathrm{d} t^2}, \boldsymbol{v}=\int \boldsymbol{a} \mathrm{d} t \\ t=\int v_x^{-1} \mathrm{~d} x=\int a_x^{-1} \mathrm{~d} v_x, x=\int \frac{v_x}{a_x} \mathrm{~d} v_x \end{gathered}

    もし aa が定数ならば, これらの積分は簡単に求めるこ とができて, 例えば

    x=v0t+at2/2=(v2v02)/2ax=v_0 t+a t^2 / 2=\left(v^2-v_0^2\right) / 2 a \text {. }

3.2: 回転運動

  1. 回転運動は, 並進運動と似ていて:

    ω=dφ/dt,ε=dω/dta=τdv/dt+nv2/R\begin{aligned} \omega & =\mathrm{d} \varphi / \mathrm{d} t, \varepsilon=\mathrm{d} \omega / \mathrm{d} t \\ \boldsymbol{a} & =\boldsymbol{\tau} \mathrm{d} v / \mathrm{d} t+\boldsymbol{n} v^2 / R \end{aligned}

3.3: 曲線運動

  1. 曲線運動は,ポイント 1 と同じだが,ベクトルは線速 度,加速度,経路長に置き換える.

3.4: 剛体の運動

  1. 剛体の運動:
    • vAcosα=vBcosβv_A \cos \alpha=v_B \cos \beta ここで, vA\boldsymbol{v}_AvB\boldsymbol{v}_B は剛体上の点 AABB の速度, α\alphaβ\betavA\boldsymbol{v}_AvB\boldsymbol{v}_B が直線 ABA B となす角.
    • 瞬間回転中心 (#質点の軌道 の曲率中心)は, a\boldsymbol{a}b\boldsymbol{b} に下ろした垂線の交点. 又は もし vA,vBAB\boldsymbol{v}_A, \boldsymbol{v}_B \perp A B ならば, vA\boldsymbol{v}_AvB\boldsymbol{v}_B の先端を結ぶ 直線と ABA B の交点.

3.5: 非慣性系

  1. 非慣性系:

    v2=v0+v1,a2=a0+a1+ω2R+aCor ここで, aCorv1. もし v1=0 なら aCor=0.\begin{array}{r} \quad \boldsymbol{v}_2=\boldsymbol{v}_0+\boldsymbol{v}_1, \boldsymbol{a}_2=\boldsymbol{a}_0+\boldsymbol{a}_1+\omega^2 \boldsymbol{R}+\boldsymbol{a}_{C o r} \\ \text { ここで, } \boldsymbol{a}_{C o r} \perp \boldsymbol{v}_1 . \text { もし } \boldsymbol{v}_1=0 \text { なら } \boldsymbol{a}_{C o r}=0 . \end{array}

3.6: 弾道問題

  1. 弾道問題:到達可能な範囲は

    yv02/(2g)gx2/(2v02)y \leq v_0^2 /(2 g)-g x^2 /\left(2 v_0^2\right)

    最適な弾道では, 初速度と終速(衝突時の速度)が垂直 になる.

3.7: 最短経路

  1. 最短経路を求めるには,Fermat と Huygens の原理が 使える.

3.8: ベクトル

  1. ベクトル(速度,加速度)を求めるには,その向きと (場合によっては傾いた)ある軸への射影を求めれば 充分.
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/4.html b/academic/physics/ipho-formulas-jpn/4.html index 984228e8..df14af48 100644 --- a/academic/physics/ipho-formulas-jpn/4.html +++ b/academic/physics/ipho-formulas-jpn/4.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 4 | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 4

Author:Anda Toshiki
Updated:4 minutes ago
Words:1.3k
Reading:5 min

4: 力学

4.1: 剛体の二次元的な平衡

  1. 剛体の二次元的な平衡 : 力についての 2 つの式とトル クについての 1 つの式. 1 (又は 2 )個の力についての 式は 1(又は 2)個のトルクについての式で代用でき る. トルクの方が良い場合が多く,原点を適切に選択 することで「退屈な」力を消すことができる. もし 2 点 のみに力がかかっているならば,(正味の)力がかかっ ている直線は一致する. 3 点であれば, 3 つの直線は 1 点で交わる.

4.2: 垂直抗力

  1. 垂直抗力と摩擦力は 1 つの力に合成でき, 垂直抗力に 対して arctanμ\arctan \mu の角度で接触点に加わる.

4.3: 並進運動と回転運動

  1. 並進運動と回転運動についての Newton の第二法則:

    F=ma,M=Iε(M=r×F)\boldsymbol{F}=m \boldsymbol{a}, \boldsymbol{M}=I \boldsymbol{\varepsilon} \quad(\boldsymbol{M}=\boldsymbol{r} \times \boldsymbol{F})

    二次元の場合には MMε\varepsilon は本質的にスカラーで, M=Fl=Ftr(lM=F l=F_t r(l は力のうでの長さ ))

4.4: 一般化座標

  1. 一般化座標. 系の状態が 1 つの変数 ξ\xi とその時間微分 ξ˙\dot{\xi} で表され,ポテンシャルエネルギーが U=U(ξ)U=U(\xi), 運動エネルギーが K=μξ2/2K=\mu \xi^2 / 2 であるならば, μξ¨=\mu \ddot{\xi}= dU(ξ)/dξ-\mathrm{d} U(\xi) / \mathrm{d} \xi. (したがって並進運動では, 力はポテン シャルエネルギーの微分)

4.5: 系質点

  1. 系が質点 mim_i で構成されているとき:

    rc=miri/mj,P=miviL=miri×vi,K=mivi2/2Iz=mi(xi2+yi2)=(x2+y2)dm\begin{aligned} & \boldsymbol{r}_c=\sum m_i \boldsymbol{r}_i / \sum m_j, \boldsymbol{P}=\sum m_i \boldsymbol{v}_i \\ & \boldsymbol{L}=\sum m_i \boldsymbol{r}_i \times \boldsymbol{v}_i, K=\sum m_i v_i^2 / 2 \\ & I_z=\sum m_i\left(x_i^2+y_i^2\right)=\int\left(x^2+y^2\right) \mathrm{d} m \\ & \end{aligned}

4.6: 質量中心の速度

  1. 質量中心の速度が vc\boldsymbol{v}_c であるような系 (添え字 cc は質量 中心についての物理量であることを示す):

    L=Lc+MΣRc×vc,K=Kc+MΣvc2/2P=Pc+MΣvc.\begin{gathered} \boldsymbol{L}=\boldsymbol{L}_c+M_{\Sigma} \boldsymbol{R}_c \times \boldsymbol{v}_c, K=K_c+M_{\Sigma} v_c^2 / 2 \\ \boldsymbol{P}=\boldsymbol{P}_c+M_{\Sigma} \boldsymbol{v}_c . \end{gathered}

4.7: Steiner 定理

  1. Steiner の定理(平行軸の定理)も同じような形で は質量中心の回転軸からの距離):

    I=Ic+mb2I=I_c+m b^2

4.8: ポイント 6

  1. ポイント 6 の P\boldsymbol{P}L\boldsymbol{L} を用いて, Newton の第二法則 :

    FΣ=dP/dt,MΣ=dL/dt\boldsymbol{F}_{\Sigma}=\mathrm{d} \boldsymbol{P} / \mathrm{d} t, \boldsymbol{M}_{\Sigma}=\mathrm{d} \boldsymbol{L} / \mathrm{d} t

4.9: ポイント 5

  1. ポイント 5 にに加えて,質量中心を通る zz 軸に対する慣性モ一メントは Iz0=I_{z 0}= i,jmimj[(xixj)2+(yiyj)2]/(2MΣ)\sum_{i, j} m_i m_j\left[\left(x_i-x_j\right)^2+\left(y_i-y_j\right)^2\right] /\left(2 M_{\Sigma}\right)

4.10: 原点に対する慣性

  1. 原点に対する慣性モ一メント θ=miri2\theta=\sum m_i r_i^2 は, 2θ=Ix+Iy+Iz2 \theta=I_x+I_y+I_z を用いることで二次元物体や等 方性のある物体の IzI_z を計算するのに有用.

4.11: 相当単振子の長

  1. 相当単振子の長さが l~\tilde{l} である物理振子 :

    ω2(l)=g/(l+Ic/ml)ω(l)=ω(l~l)=g/l~,l~=l+Ic/ml\begin{aligned} & \omega^2(l)=g /\left(l+I_c / m l\right) \\ & \omega(l)=\omega(\tilde{l}-l)=\sqrt{g / \tilde{l}}, \quad \tilde{l}=l+I_c / m l \\ & \end{aligned}

    Skip to content

    Formulas for IPhO 日本語版: Section 4

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:1.3k
    Reading:5 min

    4: 力学

    4.1: 剛体の二次元的な平衡

    1. 剛体の二次元的な平衡 : 力についての 2 つの式とトル クについての 1 つの式. 1 (又は 2 )個の力についての 式は 1(又は 2)個のトルクについての式で代用でき る. トルクの方が良い場合が多く,原点を適切に選択 することで「退屈な」力を消すことができる. もし 2 点 のみに力がかかっているならば,(正味の)力がかかっ ている直線は一致する. 3 点であれば, 3 つの直線は 1 点で交わる.

    4.2: 垂直抗力

    1. 垂直抗力と摩擦力は 1 つの力に合成でき, 垂直抗力に 対して arctanμ\arctan \mu の角度で接触点に加わる.

    4.3: 並進運動と回転運動

    1. 並進運動と回転運動についての Newton の第二法則:

      F=ma,M=Iε(M=r×F)\boldsymbol{F}=m \boldsymbol{a}, \boldsymbol{M}=I \boldsymbol{\varepsilon} \quad(\boldsymbol{M}=\boldsymbol{r} \times \boldsymbol{F})

      二次元の場合には MMε\varepsilon は本質的にスカラーで, M=Fl=Ftr(lM=F l=F_t r(l は力のうでの長さ ))

    4.4: 一般化座標

    1. 一般化座標. 系の状態が 1 つの変数 ξ\xi とその時間微分 ξ˙\dot{\xi} で表され,ポテンシャルエネルギーが U=U(ξ)U=U(\xi), 運動エネルギーが K=μξ2/2K=\mu \xi^2 / 2 であるならば, μξ¨=\mu \ddot{\xi}= dU(ξ)/dξ-\mathrm{d} U(\xi) / \mathrm{d} \xi. (したがって並進運動では, 力はポテン シャルエネルギーの微分)

    4.5: 系質点

    1. 系が質点 mim_i で構成されているとき:

      rc=miri/mj,P=miviL=miri×vi,K=mivi2/2Iz=mi(xi2+yi2)=(x2+y2)dm\begin{aligned} & \boldsymbol{r}_c=\sum m_i \boldsymbol{r}_i / \sum m_j, \boldsymbol{P}=\sum m_i \boldsymbol{v}_i \\ & \boldsymbol{L}=\sum m_i \boldsymbol{r}_i \times \boldsymbol{v}_i, K=\sum m_i v_i^2 / 2 \\ & I_z=\sum m_i\left(x_i^2+y_i^2\right)=\int\left(x^2+y^2\right) \mathrm{d} m \\ & \end{aligned}

    4.6: 質量中心の速度

    1. 質量中心の速度が vc\boldsymbol{v}_c であるような系 (添え字 cc は質量 中心についての物理量であることを示す):

      L=Lc+MΣRc×vc,K=Kc+MΣvc2/2P=Pc+MΣvc.\begin{gathered} \boldsymbol{L}=\boldsymbol{L}_c+M_{\Sigma} \boldsymbol{R}_c \times \boldsymbol{v}_c, K=K_c+M_{\Sigma} v_c^2 / 2 \\ \boldsymbol{P}=\boldsymbol{P}_c+M_{\Sigma} \boldsymbol{v}_c . \end{gathered}

    4.7: Steiner 定理

    1. Steiner の定理(平行軸の定理)も同じような形で は質量中心の回転軸からの距離):

      I=Ic+mb2I=I_c+m b^2

    4.8: ポイント 6

    1. ポイント 6 の P\boldsymbol{P}L\boldsymbol{L} を用いて, Newton の第二法則 :

      FΣ=dP/dt,MΣ=dL/dt\boldsymbol{F}_{\Sigma}=\mathrm{d} \boldsymbol{P} / \mathrm{d} t, \boldsymbol{M}_{\Sigma}=\mathrm{d} \boldsymbol{L} / \mathrm{d} t

    4.9: ポイント 5

    1. ポイント 5 にに加えて,質量中心を通る zz 軸に対する慣性モ一メントは Iz0=I_{z 0}= i,jmimj[(xixj)2+(yiyj)2]/(2MΣ)\sum_{i, j} m_i m_j\left[\left(x_i-x_j\right)^2+\left(y_i-y_j\right)^2\right] /\left(2 M_{\Sigma}\right)

    4.10: 原点に対する慣性

    1. 原点に対する慣性モ一メント θ=miri2\theta=\sum m_i r_i^2 は, 2θ=Ix+Iy+Iz2 \theta=I_x+I_y+I_z を用いることで二次元物体や等 方性のある物体の IzI_z を計算するのに有用.

    4.11: 相当単振子の長

    1. 相当単振子の長さが l~\tilde{l} である物理振子 :

      ω2(l)=g/(l+Ic/ml)ω(l)=ω(l~l)=g/l~,l~=l+Ic/ml\begin{aligned} & \omega^2(l)=g /\left(l+I_c / m l\right) \\ & \omega(l)=\omega(\tilde{l}-l)=\sqrt{g / \tilde{l}}, \quad \tilde{l}=l+I_c / m l \\ & \end{aligned}

    4.12: 慣性モーメントの係数

    1. 慣性モーメントの係数 : 円柱 12\frac{1}{2}, 球 25\frac{2}{5}, 球殼 23\frac{2}{3}, 棒 112\frac{1}{12} (端に対しては 13\frac{1}{3} ), 正方形 16\frac{1}{6}.

    4.13: よく使われる保存則

    1. よく使われる保存則:エネルギー(弾性衝突,摩擦な し), 運動量(正味の外力なし, 各方向について成立), 角運動量(正味の外トルクなし, 例えば, 外力のうでの 長さが 0 (これが 2 又は 3 点のまわりに成り立てば運 動量保存で代用できる))

    4.14: 非慣性系における見かけの力

    1. 非慣性系における見かけの力 : 慣性力 ma-m a, 遠心力 mω2Rm \omega^2 \boldsymbol{R}, Coriolis 力 2mv×Ω2 m \boldsymbol{v} \times \Omega (避けた方がよい. 速 度に垂直なので仕事はしない).

    4.15: 傾いた座標

    1. 傾いた座標:斜面上での運動については, 斜面に平行 と垂直な方向に軸をとるのがよい。このとき重力加速 度は xx 成分と yy 成分をもつ. 軸は斜交することもある が, v=vxex+vyey\boldsymbol{v}=v_x \boldsymbol{e}_x+v_y \boldsymbol{e}_y のとき vxv_xv\boldsymbol{v}xx 軸への射 影ではない.

    4.16: 2 つの物体の衝突

    1. 2 つの物体の衝突 : 保存されるのは, a) 全運動量, b) 全角運動量,c) 一方の物体の衝突点に関する角運動量, d) 全エネルギー(弾性衝突の場合, 摩擦がある場合 は, 摩擦力に垂直な方向の運動エネルギーが保存される. e) 衝突中に滑りが止まったならば,接触点の最終 速度は接触面上にある. f) 滑りが止まらなかったなら ば, 一方の物体から他方に伝わる運動量は, 接触面の 法線と arctanμ\arctan \mu の角度をなす.

    4.17: 剛体のすべての運動

    1. 剛体のすべての運動は (物体の各点の速度を見ると) 瞬 間回転中心 CC まわりの回転として表せる. 物体上の点 PPCC からの距離は PP の軌跡の曲率半径とは異なる ことに注意せよ.

    4.18: 紐の張力

    1. 紐の張力:重さのある吊り紐では, 張力の水平成分は 一定で垂直成分は下にある紐の重さにより変わる. 滑 らかな面の上の紐による(単位長さあたりの)力は,そ の曲率半径と張力で決まり, N=T/RN=T / R. 似た場合と して, 表面張力による圧力は p=2σ/Rp=2 \sigma / R. 導出には直 径に沿った圧力を調ベる.

    4.19: 液体の表面

    1. 液体の表面は(表面張力を無視すれば)等ポテンシャ ル面になる. 非圧縮性流体では, ww をポテンシャルエ ネルギーの体積密度として, p=P0wp=P_0-w.

    4.20: 非圧縮性流体に対する Bernoulli の法則

    1. 非圧縮性流体に対する Bernoulli の法則:

      p+12ρv2+ρϕ= const. p+\frac{1}{2} \rho v^2+\rho \phi=\text { const. }

      一様な重力場では ϕ=gh\phi=g h. 比熱が cp[ J/kg]c_p[\mathrm{~J} / \mathrm{kg}] である気 体では,

      12v2+cpT= const. \frac{1}{2} v^2+c_p T=\text { const. }

    4.21: 直線的な流線

    1. 直線的な流線に沾う運動量の連続性 : p+ρv2=p+\rho v^2= const.

    4.22: 断熱不変量

    1. 断熱不変量 : 振動する系の 1 周期の間のパラメータの 相対的な変化が小さければ,位相空間( xpx-p 座標で表さ れる)上に書かれるループの面積は非常に高い精度で 保存される.

    4.23: 安定性

    1. 安定性を調ベるには, a) ポテンシャルエネルギー最小 の原理,又は b) 仮想仕事の原理を用いる.

    4.24: 空間的に有限な運動に対する Virial 定理

    1. 空間的に有限な運動に対する Virial 定理:a) もし FrF \propto|\boldsymbol{r}| ならば K=U\langle K\rangle=\langle U\rangle (時間平均). b) もし Fr2F \propto|\boldsymbol{r}|^{-2} ならば 2K=U2\langle K\rangle=-\langle U\rangle.

    4.25: Tsiolkovsky 公式

    1. Tsiolkovsky の公式(ロケット): Δv=ulnMm\Delta v=u \ln \frac{M}{m}
- +M1001 80h400000v40h-400000z">,l~=l+Ic/ml

4.12: 慣性モーメントの係数

  1. 慣性モーメントの係数 : 円柱 12\frac{1}{2}, 球 25\frac{2}{5}, 球殼 23\frac{2}{3}, 棒 112\frac{1}{12} (端に対しては 13\frac{1}{3} ), 正方形 16\frac{1}{6}.

4.13: よく使われる保存則

  1. よく使われる保存則:エネルギー(弾性衝突,摩擦な し), 運動量(正味の外力なし, 各方向について成立), 角運動量(正味の外トルクなし, 例えば, 外力のうでの 長さが 0 (これが 2 又は 3 点のまわりに成り立てば運 動量保存で代用できる))

4.14: 非慣性系における見かけの力

  1. 非慣性系における見かけの力 : 慣性力 ma-m a, 遠心力 mω2Rm \omega^2 \boldsymbol{R}, Coriolis 力 2mv×Ω2 m \boldsymbol{v} \times \Omega (避けた方がよい. 速 度に垂直なので仕事はしない).

4.15: 傾いた座標

  1. 傾いた座標:斜面上での運動については, 斜面に平行 と垂直な方向に軸をとるのがよい。このとき重力加速 度は xx 成分と yy 成分をもつ. 軸は斜交することもある が, v=vxex+vyey\boldsymbol{v}=v_x \boldsymbol{e}_x+v_y \boldsymbol{e}_y のとき vxv_xv\boldsymbol{v}xx 軸への射 影ではない.

4.16: 2 つの物体の衝突

  1. 2 つの物体の衝突 : 保存されるのは, a) 全運動量, b) 全角運動量,c) 一方の物体の衝突点に関する角運動量, d) 全エネルギー(弾性衝突の場合, 摩擦がある場合 は, 摩擦力に垂直な方向の運動エネルギーが保存される. e) 衝突中に滑りが止まったならば,接触点の最終 速度は接触面上にある. f) 滑りが止まらなかったなら ば, 一方の物体から他方に伝わる運動量は, 接触面の 法線と arctanμ\arctan \mu の角度をなす.

4.17: 剛体のすべての運動

  1. 剛体のすべての運動は (物体の各点の速度を見ると) 瞬 間回転中心 CC まわりの回転として表せる. 物体上の点 PPCC からの距離は PP の軌跡の曲率半径とは異なる ことに注意せよ.

4.18: 紐の張力

  1. 紐の張力:重さのある吊り紐では, 張力の水平成分は 一定で垂直成分は下にある紐の重さにより変わる. 滑 らかな面の上の紐による(単位長さあたりの)力は,そ の曲率半径と張力で決まり, N=T/RN=T / R. 似た場合と して, 表面張力による圧力は p=2σ/Rp=2 \sigma / R. 導出には直 径に沿った圧力を調ベる.

4.19: 液体の表面

  1. 液体の表面は(表面張力を無視すれば)等ポテンシャ ル面になる. 非圧縮性流体では, ww をポテンシャルエ ネルギーの体積密度として, p=P0wp=P_0-w.

4.20: 非圧縮性流体に対する Bernoulli の法則

  1. 非圧縮性流体に対する Bernoulli の法則:

    p+12ρv2+ρϕ= const. p+\frac{1}{2} \rho v^2+\rho \phi=\text { const. }

    一様な重力場では ϕ=gh\phi=g h. 比熱が cp[ J/kg]c_p[\mathrm{~J} / \mathrm{kg}] である気 体では,

    12v2+cpT= const. \frac{1}{2} v^2+c_p T=\text { const. }

4.21: 直線的な流線

  1. 直線的な流線に沾う運動量の連続性 : p+ρv2=p+\rho v^2= const.

4.22: 断熱不変量

  1. 断熱不変量 : 振動する系の 1 周期の間のパラメータの 相対的な変化が小さければ,位相空間( xpx-p 座標で表さ れる)上に書かれるループの面積は非常に高い精度で 保存される.

4.23: 安定性

  1. 安定性を調ベるには, a) ポテンシャルエネルギー最小 の原理,又は b) 仮想仕事の原理を用いる.

4.24: 空間的に有限な運動に対する Virial 定理

  1. 空間的に有限な運動に対する Virial 定理:a) もし FrF \propto|\boldsymbol{r}| ならば K=U\langle K\rangle=\langle U\rangle (時間平均). b) もし Fr2F \propto|\boldsymbol{r}|^{-2} ならば 2K=U2\langle K\rangle=-\langle U\rangle.

4.25: Tsiolkovsky 公式

  1. Tsiolkovsky の公式(ロケット): Δv=ulnMm\Delta v=u \ln \frac{M}{m}
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/5.html b/academic/physics/ipho-formulas-jpn/5.html index 80706f8c..da397b66 100644 --- a/academic/physics/ipho-formulas-jpn/5.html +++ b/academic/physics/ipho-formulas-jpn/5.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 5 | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 5

Author:Anda Toshiki
Updated:4 minutes ago
Words:525
Reading:2 min

5. 振動と波

5.1: 減衰振動

  1. 減衰振動:

    x¨+2γx˙+ω02x=0(γ<ω)\ddot{x}+2 \gamma \dot{x}+\omega_0^2 x=0(\gamma<\omega)

    この方程式の解は ((Section 1: #3)[1#_1-3-定数係数線形微分方程式] 参照) :

    x=x0eγtsin(tω02γ2φ0)x=x_0 e^{-\gamma t} \sin \left(t \sqrt{\omega_0^2-\gamma^2}-\varphi_0\right)

    Skip to content

    Formulas for IPhO 日本語版: Section 5

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:525
    Reading:2 min

    5. 振動と波

    5.1: 減衰振動

    1. 減衰振動:

      x¨+2γx˙+ω02x=0(γ<ω)\ddot{x}+2 \gamma \dot{x}+\omega_0^2 x=0(\gamma<\omega)

      この方程式の解は ((Section 1: #3)[1#_1-3-定数係数線形微分方程式] 参照) :

      x=x0eγtsin(tω02γ2φ0)x=x_0 e^{-\gamma t} \sin \left(t \sqrt{\omega_0^2-\gamma^2}-\varphi_0\right) .

    5.10: Doppler 効果

    1. Doppler 効果 : ν=ν01+v/cs1u/cs\nu=\nu_0 \frac{1+v_{\|} / c_s}{1-u_{\|} / c_s}.

    5.11: Huygens の原理

    1. Huygens の原理 : 波面は段階的に構成される. 過去 の波面のすべての点に仮想的な波源を置く. 結果は距 離 Δx=csΔt\Delta x=c_s \Delta t で区切られた曲線(ここで Δt\Delta t は時間 間隔, csc_s は与えられた点の速度). 波は波面に垂直に 進む.
- +M1001 80h400000v40h-400000z">.

5.10: Doppler 効果

  1. Doppler 効果 : ν=ν01+v/cs1u/cs\nu=\nu_0 \frac{1+v_{\|} / c_s}{1-u_{\|} / c_s}.

5.11: Huygens の原理

  1. Huygens の原理 : 波面は段階的に構成される. 過去 の波面のすべての点に仮想的な波源を置く. 結果は距 離 Δx=csΔt\Delta x=c_s \Delta t で区切られた曲線(ここで Δt\Delta t は時間 間隔, csc_s は与えられた点の速度). 波は波面に垂直に 進む.
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/6.html b/academic/physics/ipho-formulas-jpn/6.html index f3dce1f7..f7eca576 100644 --- a/academic/physics/ipho-formulas-jpn/6.html +++ b/academic/physics/ipho-formulas-jpn/6.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 6 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 6

Author:Anda Toshiki
Updated:4 minutes ago
Words:428
Reading:1 min

6: 幾何光学,測光

6.1: Fermat 原理

  1. Fermat の原理 : 点 AA から BB への波の経路は波の移動 時間が最も短いもの.

6.2: Snell 法則

  1. Snell の法則 :

sinα1/sinα2=n2/n1=v1/v2.\sin \alpha_1 / \sin \alpha_2=n_2 / n_1=v_1 / v_2 .

6.3: 屈折率

  1. 屈折率が連続的に変化するならば,媒質を屈折率が nn で一定のいくつかの仮想的な層に分けて Snell の 法則を適用する. 光線は屈折率一定の層に沿って進む こともでき,もし全反射の条件をわずかに満たせば, n=n/r(rn^{\prime}=n / r \quad(r は曲率半径 ))

6.4: 屈折率な座標

  1. 屈折率が z\mathrm{z} 座標にのみ依存するならば, 光子の運動量 px,pyp_x, p_y とエネルギーは保存される:

kx,ky= const., k/n= const. k_x, k_y=\text { const., }|\boldsymbol{k}| / n=\text { const. }

6.5:薄いレンズの式

  1. 薄いレンズの式(符号に注意する):

1/a+1/b=1/fD1 / a+1 / b=1 / f \equiv D

6.6: Newton の式

  1. Newton の式 : 物体側焦点から物体までの距離を x1x_1, 像側焦点から像までの距離を x2x_2 とすると, x1x2=f2x_1 x_2=f^2

6.7: 像の位置を求める視差法

  1. 像の位置を求める視差法 : 目の位置と垂直に動かした ときに,鉛筆の先が像に対してずれないような位置を 探す.

6.8: レンズを通る光線の経路の幾何学的な描き方

  1. レンズを通る光線の経路の幾何学的な描き方:a) レン ズの中心を通る光線は屈折しない。b) 光軸に平行な光 線は焦点を通る,c) 屈折後, 初めに平行だった光線どうしは焦点面(焦点を通り光軸に垂直な平面)上で集 まる.d) 平面の像は平面であり,この 2 つの平面はレ ンズの平面上で交わる.

6.9: 光束

  1. 光束 Φ\Phi [単位: lumen (lm)(\operatorname{lm})] は, 光のエネルギー を示し, 眼の感度に応じて重み付けされる. 光度 [candela (cd)]は(光源から出る)立体角あたりの 光束で, I=Φ/ΩI=\Phi / \Omega. 照度 [lux(lx)][\operatorname{lux}(\mathrm{lx})] は(面に入射する) 面積あたりの光束で, E=Φ/SE=\Phi / S.

6.10: Gauss 定理

  1. 光束についての Gauss の定理 : 光度 IiI_i の点光源を囲 む閉曲面を通って外に出る光束は, Φ=4πIi\Phi=4 \pi \sum I_i. 光 源が 1 つで距離が rr のとき E=I/r2E=I / r^2

6.11: 実験のヒント

  1. 実験のヒント:紙についた油污れが周囲の紙と同じ明 るさならば,その紙は両面から同じように照らされて いる.
- +
Skip to content

Formulas for IPhO 日本語版: Section 6

Author:Anda Toshiki
Updated:2 minutes ago
Words:428
Reading:1 min

6: 幾何光学,測光

6.1: Fermat 原理

  1. Fermat の原理 : 点 AA から BB への波の経路は波の移動 時間が最も短いもの.

6.2: Snell 法則

  1. Snell の法則 :

sinα1/sinα2=n2/n1=v1/v2.\sin \alpha_1 / \sin \alpha_2=n_2 / n_1=v_1 / v_2 .

6.3: 屈折率

  1. 屈折率が連続的に変化するならば,媒質を屈折率が nn で一定のいくつかの仮想的な層に分けて Snell の 法則を適用する. 光線は屈折率一定の層に沿って進む こともでき,もし全反射の条件をわずかに満たせば, n=n/r(rn^{\prime}=n / r \quad(r は曲率半径 ))

6.4: 屈折率な座標

  1. 屈折率が z\mathrm{z} 座標にのみ依存するならば, 光子の運動量 px,pyp_x, p_y とエネルギーは保存される:

kx,ky= const., k/n= const. k_x, k_y=\text { const., }|\boldsymbol{k}| / n=\text { const. }

6.5:薄いレンズの式

  1. 薄いレンズの式(符号に注意する):

1/a+1/b=1/fD1 / a+1 / b=1 / f \equiv D

6.6: Newton の式

  1. Newton の式 : 物体側焦点から物体までの距離を x1x_1, 像側焦点から像までの距離を x2x_2 とすると, x1x2=f2x_1 x_2=f^2

6.7: 像の位置を求める視差法

  1. 像の位置を求める視差法 : 目の位置と垂直に動かした ときに,鉛筆の先が像に対してずれないような位置を 探す.

6.8: レンズを通る光線の経路の幾何学的な描き方

  1. レンズを通る光線の経路の幾何学的な描き方:a) レン ズの中心を通る光線は屈折しない。b) 光軸に平行な光 線は焦点を通る,c) 屈折後, 初めに平行だった光線どうしは焦点面(焦点を通り光軸に垂直な平面)上で集 まる.d) 平面の像は平面であり,この 2 つの平面はレ ンズの平面上で交わる.

6.9: 光束

  1. 光束 Φ\Phi [単位: lumen (lm)(\operatorname{lm})] は, 光のエネルギー を示し, 眼の感度に応じて重み付けされる. 光度 [candela (cd)]は(光源から出る)立体角あたりの 光束で, I=Φ/ΩI=\Phi / \Omega. 照度 [lux(lx)][\operatorname{lux}(\mathrm{lx})] は(面に入射する) 面積あたりの光束で, E=Φ/SE=\Phi / S.

6.10: Gauss 定理

  1. 光束についての Gauss の定理 : 光度 IiI_i の点光源を囲 む閉曲面を通って外に出る光束は, Φ=4πIi\Phi=4 \pi \sum I_i. 光 源が 1 つで距離が rr のとき E=I/r2E=I / r^2

6.11: 実験のヒント

  1. 実験のヒント:紙についた油污れが周囲の紙と同じ明 るさならば,その紙は両面から同じように照らされて いる.
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/7.html b/academic/physics/ipho-formulas-jpn/7.html index e211fe62..d1cb6fa6 100644 --- a/academic/physics/ipho-formulas-jpn/7.html +++ b/academic/physics/ipho-formulas-jpn/7.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 7 | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 7

Author:Anda Toshiki
Updated:4 minutes ago
Words:732
Reading:3 min

7: 波動光学

7.1: Huygens の原理に基づいた回折

  1. Huygens の原理に基づいた回折 : 障害物が波面を切断 すると波面は小さな断片に分割され,それが仮想的な 点波源となり,観測点での波の振幅はこれらの波源か らの寄与の重ね合わせとなる.

7.2: 二重スリット

  1. 二重スリット(幅は da,λ)d \ll a, \lambda) による干渉:強 め合う角 φmax=arcsin(nλ/d),nZ.I\varphi_{\max }=\arcsin (n \lambda / d), n \in \mathbb{Z} . I \propto cos2(ka2sinφ),(k=2π/λ)\cos ^2\left(k \frac{a}{2} \sin \varphi\right),(k=2 \pi / \lambda)

7.3: 単スリット-弱め合う角

  1. 単スリット:弱め合う角: φmin =arcsin(nλ/d),n\varphi_{\text {min }}=\arcsin (n \lambda / d), n \in Z,n0\mathbb{Z}, n \neq 0. 中央の強め合う部分は n=±1n=\pm 1 の間である ことに注意せよ. Isin2(kd2sinφ)/sinφI \propto \sin ^2\left(k \frac{d}{2} \sin \varphi\right) / \sin \varphi

7.4: 回折格子

  1. 回折格子:主な強め合う角はポイント 2 と同じで, 主 な強め合う角の幅は dd を回折格子の正味の長さとすれ ばポイント 3 と同じ. nn 番目の明線のスペクトルの分 解能は,溝の総数を NN 本として λΔλ=nN\frac{\lambda}{\Delta \lambda}=n N.

7.5: 分光器の分解能

  1. 分光器の分解能 : 最短の光線と最長の光線の光学距離 の差を LL として, λΔλ=Lλ\frac{\lambda}{\Delta \lambda}=\frac{L}{\lambda}.

7.6: プリズムの分解能

  1. プリズムの分解能 :λΔλ=adn dλ: \frac{\lambda}{\Delta \lambda}=a \frac{\mathrm{d} n}{\mathrm{~d} \lambda}

7.7: 角度距離

  1. 理想的な望遠鏡 (レンズ) で 2 点を解像するときの角度距離 : φ1.22λ/d\varphi \approx 1.22 \lambda / d. この角度では, 一方の点の中 心が他方の点の最初の回折最小值に当たる.

7.8: Bragg の法則

  1. Bragg の法則:間隔が dd の平行な結晶面の組は, 2dsinθ=nλ2 d \sin \theta=n \lambda ならば X\mathrm{X} 線を反射する. ここで θ\theta は結 晶面と X 線がなす角 (かすめ角).

7.9: 高密度電体媒質反射

  1. 光学的に高密度な誘電体媒質による反射 : 位相が π\pi ず れる. 半透明の薄膜では ϕ+ϕ=π\phi_{\rightarrow}+\phi_{\leftarrow}=\pi. ここで ϕ\phi_{\rightarrow}ϕ\phi_{\leftarrow} は反射波と透過波の位相差(矢印は入射方向を 示す)

7.10: Fabry-Pérot 干渉計

  1. Fabry-Pérot 干渉計 : 高い反射率 r(1r1)r(1-r \ll 1) を持 つ 2 枚の平行な半透明の鏡. 分解能は νΔν2aλ(1r)\frac{\nu}{\Delta \nu} \approx \frac{2 a}{\lambda(1-r)}. 5 つの平面波 (干渉計の前で左右に進む波, 内部を左右 に進む波,後ろを進む波)を設定して境界条件を課す ことで,透過スペクトルを求められる.

7.11: コヒーレントな電磁波

  1. コヒーレントな電磁波: 電場をベクトル为で表し, ベク トル間の角度を位相差とする. 屈折率が n=n(ω)=n=n(\omega)= ε(ω)\sqrt{\varepsilon(\omega)}
- +M1001 80h400000v40h-400000z"> (普通 μ1\mu \approx 1 ) であることに注意せよ. エネ ルギー流密度(単位面積を通過する単位時間あたりの エネルギー): I=cnε0E2=cnμ0B2(EI=c n \varepsilon_0 E^2=\frac{c}{n \mu_0} B^2(EBB は実 効值)

7.12: Malus の法則

  1. Malus の法則 : 直線偏光が角度 φ\varphi で偏光板を通過する と I=I0cos2φI=I_0 \cos ^2 \varphi

7.13: 1/4 波長版

  1. 1/41 / 4 波長版 : 直線偏光成分間の位相が π/2\pi / 2 ずれる.

7.14: Brewster 角

  1. Brewster 角: 入射角が tanφ=n\tan \varphi=n を満たすとき, 反 射波と屈折波が垂直になり反射波は直線偏光となる.

7.15: 光学素子による回折

  1. 光学素子による回折 : レンズやプリズムなどを通る光 の光学距離を計算する必要はなく, 図形的に考える. 例えば,双プリズムは二重スリットによる回折と同じ 回折をする.

7.16: 光ファイバー

  1. 光ファイバー:Mach-Zehnder 干渉計は二重スリッ トによる干渉と, 円形共振器は Fabry-Pérot 干渉計 と似ている. Bragg フィルターは X\mathrm{X} 線の場合と同 じように働く. シングルモードの光ファイバーでは, Δn/n12(λ/d)2\Delta n / n \approx \frac{1}{2}(\lambda / d)^2.
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/8.html b/academic/physics/ipho-formulas-jpn/8.html index 74e47774..5fdbf16e 100644 --- a/academic/physics/ipho-formulas-jpn/8.html +++ b/academic/physics/ipho-formulas-jpn/8.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 8 | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 8

Author:Anda Toshiki
Updated:4 minutes ago
Words:568
Reading:2 min

8: 電気回路

8.1: V=I R, P=V I

  1. V=IR,P=VIV=I R, P=V I

    R直列 =Ri,R並列 1=Ri1R_{\text {直列 }}=\sum R_i, R_{\text {並列 }}^{-1}=\sum R_i^{-1}

8.2: Kirchhoff の法則

  1. Kirchhoff の法則 :

     節点 I=0,閉路 V=0\sum_{\substack{\text { 節点 }}} I=0, \sum_{\text {閉路 }} V=0

8.3: ポイント 2 の方程式を減らすために

  1. ポイント 2 の方程式を減らすために: 節点電位法. ルー プ電流法. 等価回路 (3 端子の場合 \Rightarrow \triangle 又YY の形, 起電力のある 2 端子の場合 \Rightarrow 抵抗と電池の直列)

8.4: 無限につながる抵抗

  1. 無限につながる抵抗 : 無限に続く格子の隣り合う節点 間で,自己相似性を使う。鏡像法の一般化された方法.

8.5: 交流回路

  1. 交流回路: RRZZ に置き換えてポイント 141 \sim 4 を用 いる.

    ZR=R,ZC=1/iωC,ZL=iωLφ=argZ,Veff =ZIeff P=VIcos(argZ)=Ii2Ri\begin{gathered} Z_R=R, Z_C=1 / i \omega C, Z_L=i \omega L \\ \varphi=\arg Z, V_{\text {eff }}=|Z| I_{\text {eff }} \\ P=|V||I| \cos (\arg Z)=\sum I_i^2 R_i \end{gathered}

8.6: 特性時間

  1. 特性時間: τRC=RC,τLR=L/R.ωLC=\tau_{R C}=R C, \tau_{L R}=L / R . \omega_{L C}= 1/LC1 / \sqrt{L C}
- +M834 80h400000v40h-400000z"> が成立.
+ \ No newline at end of file diff --git a/academic/physics/ipho-formulas-jpn/9.html b/academic/physics/ipho-formulas-jpn/9.html index 4a8e87b5..20b04488 100644 --- a/academic/physics/ipho-formulas-jpn/9.html +++ b/academic/physics/ipho-formulas-jpn/9.html @@ -5,15 +5,15 @@ Formulas for IPhO 日本語版: Section 9 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Formulas for IPhO 日本語版: Section 9

Author:Anda Toshiki
Updated:4 minutes ago
Words:950
Reading:4 min

9: 電磁気学

9.1: Coulomb の法則

  1. F=kq1q2/r2,U=kq1q2/rF=k q_1 q_2 / r^2, U=k q_1 q_2 / r で, Kepler の法則が 使える (Section 12 参照).

9.2: Gauss の法則

  1. Gauss の法則 : BdS=0\oint \boldsymbol{B} \cdot \mathrm{d} \boldsymbol{S}=0,

    εEdS=Q,gdS=4πGM\oint \varepsilon \boldsymbol{E} \cdot \mathrm{d} \boldsymbol{S}=Q, \oint \boldsymbol{g} \cdot \mathrm{d} \boldsymbol{S}=-4 \pi G M

9.3: 循環定理

  1. 循環定理 :

    Edl=0(=Φ˙),Bdlμ=I,gdl=0\oint \boldsymbol{E} \cdot \mathrm{d} \boldsymbol{l}=0(=\dot{\Phi}), \oint \frac{\boldsymbol{B} \cdot \mathrm{d} \boldsymbol{l}}{\mu}=I, \oint \boldsymbol{g} \cdot \mathrm{d} \boldsymbol{l}=0

9.4: 電流素片により生じる磁束密度

  1. 電流素片により生じる磁束密度 :

    dB=μI4πdl×err2.\mathrm{d} \boldsymbol{B}=\frac{\mu I}{4 \pi} \frac{\mathrm{d} \boldsymbol{l} \times \boldsymbol{e}_r}{r^2} .

    したがって電流 II が流れる円形回路の中心では B=μ0I2rB=\frac{\mu_0 I}{2 r}.

9.5: ローレンツ力

  1. F=e(E+v×B),F=I×Bl\boldsymbol{F}=e(\boldsymbol{E}+\boldsymbol{v} \times \boldsymbol{B}), \boldsymbol{F}=\boldsymbol{I} \times \boldsymbol{B} l.

9.6: Gauss の定理と循環定理より

  1. Gauss の定理と循環定理より:帯電した導線について E=σ2πε0rE=\frac{\sigma}{2 \pi \varepsilon_0 r}, 電流が流れる導線について B=μ0I2πrB=\frac{\mu_0 I}{2 \pi r}. 帯電した面について E=σ2ε0E=\frac{\sigma}{2 \varepsilon_0}, 電流が流れる面につい て B=μ0i2B=\frac{\mu_0 i}{2}. 一様に帯電した球殼(又は無限に長い円 筒)の内部で E=0E=0, 軸に沿って表面に電流が流れる 円筒の内部で B=0B=0. 密度 ρ\rho で一様に帯電, 又は一様 な電流 i\boldsymbol{i} が流れる, 球 (d=3)/(d=3) / 円柱 (d2)/(d-2) / 平面 (d=1)(d=1) の内部で,

    E=ρεdr,B=1μdi×r\boldsymbol{E}=\frac{\rho}{\varepsilon d} \boldsymbol{r}, \boldsymbol{B}=\frac{1}{\mu d} \boldsymbol{i} \times \boldsymbol{r}

9.7: 長いソレノイド

  1. 長いソレノイド: 内部で B=μnIB=\mu n I, 外部で B=0B=0. 磁束 Φ=NBS(n=Nl)\Phi=N B S\left(n=\frac{N}{l}\right). インダクタンス L=L= Φ/I=μn2V\Phi / I=\mu n^2 V. 短いソレノイド :B=μnIΩ4π(Ω: B_{\|}=\frac{\mu n I \Omega}{4 \pi}(\Omega は 立体角).

9.8: 磁場を小型コイルや衝撃検流計で測定する

  1. 磁場を小型コイルや衝撃検流計で測定する: q=q= VR dt=NSΔB/R\int \frac{V}{R} \mathrm{~d} t=N S \Delta B / R.

9.9: 静電場のエネルギー

  1. 静電場のエネルギー:

    U=ki<jqiqjrij=12ϕ(r)dq, dq=ρ(r)dVU=k \sum_{i<j} \frac{q_i q_j}{r_{i j}}=\frac{1}{2} \int \phi(\boldsymbol{r}) \mathrm{d} q, \mathrm{~d} q=\rho(\boldsymbol{r}) \mathrm{d} V

9.10: 一様に帯電した球面や円筒面の各部分の間に働く力

  1. 一様に帯電した球面や円筒面の各部分の間に働く力 : 帯電による力を静水圧による力に置き換える.

9.11: 全ての電荷

  1. 全ての電荷が距離 rr にある場合(例えば,不均一に帯 電した球やリングの中心) ϕϕ=kQ/r\phi \phi=k Q / r

9.12: 外部電荷

  1. 外部電荷によって引き起こされる正味の電荷(又は電 位)を求めるには, 電荷を「出現」させて問題を対称的 にし,重ね合わせの原理を用いる.

9.14: 導体

  1. 導体は電荷や電場を遮蔽する.例えば,中空の球体の 内部の電荷分布は外から見えない(あたかも QQ という 電荷を持った導電性の球があるように見える).

9.15: 静電容量

  1. 静電容量: C=εS/dC=\varepsilon S / d (平板), 4πεr4 \pi \varepsilon r (球), 2πεl(lnR/r)12 \pi \varepsilon l(\ln R / r)^{-1} (同軸円筒).

9.16: 双極子モーメント

  1. 双極子モーメント:

    pe=qiri=qd,pμ=IS\boldsymbol{p}_e=\sum q_i \boldsymbol{r}_i=q \boldsymbol{d}, \boldsymbol{p}_\mu=I \boldsymbol{S}

9.17: 双極子場

  1. 双極子場 : ϕ=kper/r2,E,Br3\phi=k \boldsymbol{p} \cdot \boldsymbol{e}_r / r^2, E, B \propto r^{-3}

9.18: 双極子に働く力

  1. 双極子に働く力 : F=(peE),F=(pμB)F=\left(\boldsymbol{p}_e \cdot \boldsymbol{E}\right)^{\prime}, F=\left(\boldsymbol{p}_\mu \cdot \boldsymbol{B}\right)^{\prime} [訳 者注 : ここの微分はむしろ grad\operatorname{grad} である]. 2 つの双極 子間の相互作用 :Fr4: F \propto r^{-4}.

9.19: 磁気双極子としての点電荷

  1. 磁気双極子としての点電荷 : pμΦv2/Bp_\mu \propto \Phi \propto v_{\perp}^2 / B は断熱 不変量 (Section 4: #22 参照).

9.20: 鏡像法

  1. 鏡像法 : 接地された(磁石の場合は超電導の)平面が鏡 の役割をする. 接地された(又は孤立した)球体の場 は, 球体の内部にある 1 つ(又は 2 つ)の架空の電荷 のつくる場として求められる. 平面導波管(金属板の 間のスリット)内の場は, 電磁平面波の重ね合わせと して求められる.

9.21: 一様(電)場中の球 (円柱) の分極

  1. 一様(電)場中の球 (円柱) の分極 : (+ρ(+\rhoρ-\rho に一 様に帯電した球 (円柱) の重ね合わせで, dEd \propto E.

9.22: 渦電流

  1. 渦電流: 電流損失密度 B2v2/ρ.1\approx B^2 v^2 / \rho .1 回の通過で与え られる運動量 : FτB2a3d/ρF \tau \approx B^2 a^3 d / \rho (ここで dd は厚さ, aa は大きさ).
- +
Skip to content

Formulas for IPhO 日本語版: Section 9

Author:Anda Toshiki
Updated:2 minutes ago
Words:950
Reading:4 min

9: 電磁気学

9.1: Coulomb の法則

  1. F=kq1q2/r2,U=kq1q2/rF=k q_1 q_2 / r^2, U=k q_1 q_2 / r で, Kepler の法則が 使える (Section 12 参照).

9.2: Gauss の法則

  1. Gauss の法則 : BdS=0\oint \boldsymbol{B} \cdot \mathrm{d} \boldsymbol{S}=0,

    εEdS=Q,gdS=4πGM\oint \varepsilon \boldsymbol{E} \cdot \mathrm{d} \boldsymbol{S}=Q, \oint \boldsymbol{g} \cdot \mathrm{d} \boldsymbol{S}=-4 \pi G M

9.3: 循環定理

  1. 循環定理 :

    Edl=0(=Φ˙),Bdlμ=I,gdl=0\oint \boldsymbol{E} \cdot \mathrm{d} \boldsymbol{l}=0(=\dot{\Phi}), \oint \frac{\boldsymbol{B} \cdot \mathrm{d} \boldsymbol{l}}{\mu}=I, \oint \boldsymbol{g} \cdot \mathrm{d} \boldsymbol{l}=0

9.4: 電流素片により生じる磁束密度

  1. 電流素片により生じる磁束密度 :

    dB=μI4πdl×err2.\mathrm{d} \boldsymbol{B}=\frac{\mu I}{4 \pi} \frac{\mathrm{d} \boldsymbol{l} \times \boldsymbol{e}_r}{r^2} .

    したがって電流 II が流れる円形回路の中心では B=μ0I2rB=\frac{\mu_0 I}{2 r}.

9.5: ローレンツ力

  1. F=e(E+v×B),F=I×Bl\boldsymbol{F}=e(\boldsymbol{E}+\boldsymbol{v} \times \boldsymbol{B}), \boldsymbol{F}=\boldsymbol{I} \times \boldsymbol{B} l.

9.6: Gauss の定理と循環定理より

  1. Gauss の定理と循環定理より:帯電した導線について E=σ2πε0rE=\frac{\sigma}{2 \pi \varepsilon_0 r}, 電流が流れる導線について B=μ0I2πrB=\frac{\mu_0 I}{2 \pi r}. 帯電した面について E=σ2ε0E=\frac{\sigma}{2 \varepsilon_0}, 電流が流れる面につい て B=μ0i2B=\frac{\mu_0 i}{2}. 一様に帯電した球殼(又は無限に長い円 筒)の内部で E=0E=0, 軸に沿って表面に電流が流れる 円筒の内部で B=0B=0. 密度 ρ\rho で一様に帯電, 又は一様 な電流 i\boldsymbol{i} が流れる, 球 (d=3)/(d=3) / 円柱 (d2)/(d-2) / 平面 (d=1)(d=1) の内部で,

    E=ρεdr,B=1μdi×r\boldsymbol{E}=\frac{\rho}{\varepsilon d} \boldsymbol{r}, \boldsymbol{B}=\frac{1}{\mu d} \boldsymbol{i} \times \boldsymbol{r}

9.7: 長いソレノイド

  1. 長いソレノイド: 内部で B=μnIB=\mu n I, 外部で B=0B=0. 磁束 Φ=NBS(n=Nl)\Phi=N B S\left(n=\frac{N}{l}\right). インダクタンス L=L= Φ/I=μn2V\Phi / I=\mu n^2 V. 短いソレノイド :B=μnIΩ4π(Ω: B_{\|}=\frac{\mu n I \Omega}{4 \pi}(\Omega は 立体角).

9.8: 磁場を小型コイルや衝撃検流計で測定する

  1. 磁場を小型コイルや衝撃検流計で測定する: q=q= VR dt=NSΔB/R\int \frac{V}{R} \mathrm{~d} t=N S \Delta B / R.

9.9: 静電場のエネルギー

  1. 静電場のエネルギー:

    U=ki<jqiqjrij=12ϕ(r)dq, dq=ρ(r)dVU=k \sum_{i<j} \frac{q_i q_j}{r_{i j}}=\frac{1}{2} \int \phi(\boldsymbol{r}) \mathrm{d} q, \mathrm{~d} q=\rho(\boldsymbol{r}) \mathrm{d} V

9.10: 一様に帯電した球面や円筒面の各部分の間に働く力

  1. 一様に帯電した球面や円筒面の各部分の間に働く力 : 帯電による力を静水圧による力に置き換える.

9.11: 全ての電荷

  1. 全ての電荷が距離 rr にある場合(例えば,不均一に帯 電した球やリングの中心) ϕϕ=kQ/r\phi \phi=k Q / r

9.12: 外部電荷

  1. 外部電荷によって引き起こされる正味の電荷(又は電 位)を求めるには, 電荷を「出現」させて問題を対称的 にし,重ね合わせの原理を用いる.

9.14: 導体

  1. 導体は電荷や電場を遮蔽する.例えば,中空の球体の 内部の電荷分布は外から見えない(あたかも QQ という 電荷を持った導電性の球があるように見える).

9.15: 静電容量

  1. 静電容量: C=εS/dC=\varepsilon S / d (平板), 4πεr4 \pi \varepsilon r (球), 2πεl(lnR/r)12 \pi \varepsilon l(\ln R / r)^{-1} (同軸円筒).

9.16: 双極子モーメント

  1. 双極子モーメント:

    pe=qiri=qd,pμ=IS\boldsymbol{p}_e=\sum q_i \boldsymbol{r}_i=q \boldsymbol{d}, \boldsymbol{p}_\mu=I \boldsymbol{S}

9.17: 双極子場

  1. 双極子場 : ϕ=kper/r2,E,Br3\phi=k \boldsymbol{p} \cdot \boldsymbol{e}_r / r^2, E, B \propto r^{-3}

9.18: 双極子に働く力

  1. 双極子に働く力 : F=(peE),F=(pμB)F=\left(\boldsymbol{p}_e \cdot \boldsymbol{E}\right)^{\prime}, F=\left(\boldsymbol{p}_\mu \cdot \boldsymbol{B}\right)^{\prime} [訳 者注 : ここの微分はむしろ grad\operatorname{grad} である]. 2 つの双極 子間の相互作用 :Fr4: F \propto r^{-4}.

9.19: 磁気双極子としての点電荷

  1. 磁気双極子としての点電荷 : pμΦv2/Bp_\mu \propto \Phi \propto v_{\perp}^2 / B は断熱 不変量 (Section 4: #22 参照).

9.20: 鏡像法

  1. 鏡像法 : 接地された(磁石の場合は超電導の)平面が鏡 の役割をする. 接地された(又は孤立した)球体の場 は, 球体の内部にある 1 つ(又は 2 つ)の架空の電荷 のつくる場として求められる. 平面導波管(金属板の 間のスリット)内の場は, 電磁平面波の重ね合わせと して求められる.

9.21: 一様(電)場中の球 (円柱) の分極

  1. 一様(電)場中の球 (円柱) の分極 : (+ρ(+\rhoρ-\rho に一 様に帯電した球 (円柱) の重ね合わせで, dEd \propto E.

9.22: 渦電流

  1. 渦電流: 電流損失密度 B2v2/ρ.1\approx B^2 v^2 / \rho .1 回の通過で与え られる運動量 : FτB2a3d/ρF \tau \approx B^2 a^3 d / \rho (ここで dd は厚さ, aa は大きさ).
+ \ No newline at end of file diff --git a/academic/vocabulary/2023/02/2023-02-27.html b/academic/vocabulary/2023/02/2023-02-27.html index 51563407..e01ad299 100644 --- a/academic/vocabulary/2023/02/2023-02-27.html +++ b/academic/vocabulary/2023/02/2023-02-27.html @@ -5,15 +5,15 @@ 2023-2-27: Vocabulary | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

2023-2-27: Vocabulary

Author:Anda Toshiki
Updated:4 minutes ago
Words:299
Reading:1 min

This table of vocabularies are from "Sadlier Vocabulary Workshop-Level G (Unit 4)" with their corresponding textbook definitions and part of speeches (from some of them) made into a collection.

VocabularyDefinition
Atrophy(n.) the wasting away of a body organ or tissue; any progressive decline or failure; (v.) to waste away
BastionA fortified place, stronghold
ConcordA state of agreement, harmony, unanimity; a treaty, pact, covenant
Consummate(adj.) complete or perfect in the highest degree; (v.) to bring to a state of completion or perfection
Disarray(n.) disorder, confusion; (v.) to throw into disorder
ExigencyUrgency, pressure; urgent demand, pressing need; an emergency
FlotsamFloating debris; homeless, impoverished people
FreneticFrenzied, highly agitated
GleanTo gather bit by bit; to gather small quantities of grain left in a field by the reapers.
Grouse(n.) A type of game bird; a complaint; (v.) to complain, grumble
IncarcerateTo imprison, confine, jail
Incumbent(adj.) obligatory, required; (n.) one who holds a specific office at the time spoken of
JocularHumorous, jesting, jolly, joking
LudicrousRidiculous, laughable, absurd
MordantBiting or caustic in thought, manner, or style; sharply or bitterly harsh.
Nettle(n.) a prickly or stinging plant; (v.) to arouse displeasure, impatience, or anger; to vex or irritate severely
PecuniaryConsisting of or measured in money; of or related to money
PusillanimousContemptibly cowardly or mean-spirited
RecumbentIn a reclining position, lying down, in the posture of one sleeping or resting.
StratagemA scheme to outwit or deceive an opponent or to gain and end.

Reference

- +
Skip to content

2023-2-27: Vocabulary

Author:Anda Toshiki
Updated:2 minutes ago
Words:299
Reading:1 min

This table of vocabularies are from "Sadlier Vocabulary Workshop-Level G (Unit 4)" with their corresponding textbook definitions and part of speeches (from some of them) made into a collection.

VocabularyDefinition
Atrophy(n.) the wasting away of a body organ or tissue; any progressive decline or failure; (v.) to waste away
BastionA fortified place, stronghold
ConcordA state of agreement, harmony, unanimity; a treaty, pact, covenant
Consummate(adj.) complete or perfect in the highest degree; (v.) to bring to a state of completion or perfection
Disarray(n.) disorder, confusion; (v.) to throw into disorder
ExigencyUrgency, pressure; urgent demand, pressing need; an emergency
FlotsamFloating debris; homeless, impoverished people
FreneticFrenzied, highly agitated
GleanTo gather bit by bit; to gather small quantities of grain left in a field by the reapers.
Grouse(n.) A type of game bird; a complaint; (v.) to complain, grumble
IncarcerateTo imprison, confine, jail
Incumbent(adj.) obligatory, required; (n.) one who holds a specific office at the time spoken of
JocularHumorous, jesting, jolly, joking
LudicrousRidiculous, laughable, absurd
MordantBiting or caustic in thought, manner, or style; sharply or bitterly harsh.
Nettle(n.) a prickly or stinging plant; (v.) to arouse displeasure, impatience, or anger; to vex or irritate severely
PecuniaryConsisting of or measured in money; of or related to money
PusillanimousContemptibly cowardly or mean-spirited
RecumbentIn a reclining position, lying down, in the posture of one sleeping or resting.
StratagemA scheme to outwit or deceive an opponent or to gain and end.

Reference

+ \ No newline at end of file diff --git a/academic/vocabulary/index.html b/academic/vocabulary/index.html index 1217c2e3..21464abf 100644 --- a/academic/vocabulary/index.html +++ b/academic/vocabulary/index.html @@ -5,15 +5,15 @@ Welcome to My Vocabulary List! | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
Skip to content

Welcome to My Vocabulary List!

Author:Anda Toshiki
Updated:4 minutes ago
Words:5
Reading:1 min
- +
Skip to content

Welcome to My Vocabulary List!

Author:Anda Toshiki
Updated:2 minutes ago
Words:5
Reading:1 min
+ \ No newline at end of file diff --git a/application/markdown-it-katex/how-to-use.html b/application/markdown-it-katex/how-to-use.html index 2a1fe43f..0aa93b90 100644 --- a/application/markdown-it-katex/how-to-use.html +++ b/application/markdown-it-katex/how-to-use.html @@ -5,15 +5,15 @@ @andatoshiki/markdown-it-katex | Toshiki's Note - + - + - + - + @@ -36,39 +36,39 @@ -
Skip to content

@andatoshiki/markdown-it-katex

Author:Anda Toshiki
Updated:4 minutes ago
Words:1.1k
Reading:7 min

Add graceful KaTeX\KaTeX rendering to your Markdown like a charm with markdown-it plugin.

1: Installation

Before you start using this plugin, make sure you have already installed the default markdown-it parser; if not, please run the following command or refer to the official markdown-it documentation.

sh
$ npm install markdown-it --save
$ npm install markdown-it --save

First install package with your preferred package manager (npm, yarn, pnpm), or include javascript before the closing </body> for markdown-it-katex's core utils to be loaded for the static page.

sh
$ npm install -D @andatoshiki/markdown-it-katex
$ npm install -D @andatoshiki/markdown-it-katex
sh
$ yarn add --dev @andatoshiki/markdown-it-katex
$ yarn add --dev @andatoshiki/markdown-it-katex
sh
$ pnpm add -D @andatoshiki/markdown-it-katex
$ pnpm add -D @andatoshiki/markdown-it-katex
html
<!-- your other body contents ... -->
-    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
-</body>
<!-- your other body contents ... -->
-    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
-</body>

Including KaTeX CSS is necessary in the way you are convenient with, either link the stylesheet from a third party CDN into the local HTML <head> tag or import it into a currently linked CSS stylesheets to enable styles for KaTeX globally as follows,

Or, you could clone or download the entire repository source of KaTeX and self load the fonts/styles/scripts locally, but if you prefer loading from third-party CDN with faster load speed when deployed to save your server resources, the following CDN links might be your choice, you can always switch to other platforms based on your need.

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
html
<link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
<link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
html
<link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
<link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
html
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
html
<link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
<link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
scss
// ... your other styles
-@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
// ... your other styles
-@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';

If you are using the default markdown-it parser, I personally recommend that you use the GitHub markdown CSS (github-markdown-css) for styling your HTML output with a similar style replica of GitHub's markdown styling to your familiarity.

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />

This forked project maintained by Anda Toshiki comes with the update of KaTeX components with higher style version support (this documentation uses KaTeX version 16.0, without hassels), later versions may works, but no guarantees are given by the developers, if you are not obsessed with the latest released version, 16.0 may fits your need for loading KaTeX on a personal blog site or small educational sites; yet it should work fully functionally.

Warning

Since this project is a fork of the original markdown-it-katex project that hasn't been receiving any active updates of its code source for years, the latest katex style version supported is somewhere around ver. 0.9.0 which clearly is outdated and results in broken styles with overflowing and other potential bug presents.

2: Usage

RTo render equations, you need to include the markdown-it-katex plugin in the markdown-it components in your JavaScript or TypeScript file as follows,

js
var md = require('markdown-it')(),
-    mk = require('andatoshiki/markdown-it-katex')
+    
Skip to content

@andatoshiki/markdown-it-katex

Author:Anda Toshiki
Updated:2 minutes ago
Words:1.1k
Reading:7 min

Add graceful KaTeX\KaTeX rendering to your Markdown like a charm with markdown-it plugin.

1: Installation

Before you start using this plugin, make sure you have already installed the default markdown-it parser; if not, please run the following command or refer to the official markdown-it documentation.

sh
$ npm install markdown-it --save
$ npm install markdown-it --save

First install package with your preferred package manager (npm, yarn, pnpm), or include javascript before the closing </body> for markdown-it-katex's core utils to be loaded for the static page.

sh
$ npm install -D @andatoshiki/markdown-it-katex
$ npm install -D @andatoshiki/markdown-it-katex
sh
$ yarn add --dev @andatoshiki/markdown-it-katex
$ yarn add --dev @andatoshiki/markdown-it-katex
sh
$ pnpm add -D @andatoshiki/markdown-it-katex
$ pnpm add -D @andatoshiki/markdown-it-katex
html
<!-- your other body contents ... -->
+    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
+</body>
<!-- your other body contents ... -->
+    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
+</body>

Including KaTeX CSS is necessary in the way you are convenient with, either link the stylesheet from a third party CDN into the local HTML <head> tag or import it into a currently linked CSS stylesheets to enable styles for KaTeX globally as follows,

Or, you could clone or download the entire repository source of KaTeX and self load the fonts/styles/scripts locally, but if you prefer loading from third-party CDN with faster load speed when deployed to save your server resources, the following CDN links might be your choice, you can always switch to other platforms based on your need.

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
html
<link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
<link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
html
<link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
<link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
html
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
html
<link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
<link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
scss
// ... your other styles
+@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
// ... your other styles
+@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';

If you are using the default markdown-it parser, I personally recommend that you use the GitHub markdown CSS (github-markdown-css) for styling your HTML output with a similar style replica of GitHub's markdown styling to your familiarity.

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />

This forked project maintained by Anda Toshiki comes with the update of KaTeX components with higher style version support (this documentation uses KaTeX version 16.0, without hassels), later versions may works, but no guarantees are given by the developers, if you are not obsessed with the latest released version, 16.0 may fits your need for loading KaTeX on a personal blog site or small educational sites; yet it should work fully functionally.

Warning

Since this project is a fork of the original markdown-it-katex project that hasn't been receiving any active updates of its code source for years, the latest katex style version supported is somewhere around ver. 0.9.0 which clearly is outdated and results in broken styles with overflowing and other potential bug presents.

2: Usage

RTo render equations, you need to include the markdown-it-katex plugin in the markdown-it components in your JavaScript or TypeScript file as follows,

js
var md = require('markdown-it')(),
+    mk = require('andatoshiki/markdown-it-katex')
 
-md.use(mk)
+md.use(mk)
 
-// double backslash is required for javascript strings, but not html input
-var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
var md = require('markdown-it')(),
-    mk = require('andatoshiki/markdown-it-katex')
+// double backslash is required for javascript strings, but not html input
+var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
var md = require('markdown-it')(),
+    mk = require('andatoshiki/markdown-it-katex')
 
-md.use(mk)
+md.use(mk)
 
-// double backslash is required for javascript strings, but not html input
-var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
ts
import * as mk from 'markdown-it-katex'
-import * as MarkdownIt from '@andatoshiki/markdown-it'
+// double backslash is required for javascript strings, but not html input
+var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
ts
import * as mk from 'markdown-it-katex'
+import * as MarkdownIt from '@andatoshiki/markdown-it'
 
-const md = new MarkdownIt()
-md.use(mk)
+const md = new MarkdownIt()
+md.use(mk)
 
-// double backslash is not required for TypeScript strings or template literals
-const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
import * as mk from 'markdown-it-katex'
-import * as MarkdownIt from '@andatoshiki/markdown-it'
+// double backslash is not required for TypeScript strings or template literals
+const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
import * as mk from 'markdown-it-katex'
+import * as MarkdownIt from '@andatoshiki/markdown-it'
 
-const md = new MarkdownIt()
-md.use(mk)
+const md = new MarkdownIt()
+md.use(mk)
 
-// double backslash is not required for TypeScript strings or template literals
-const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')

3: Configuration

The following list of variable are the customizable components of markdown-it-katex, adjust to your needs,

  • katex: You can change KaTeX version by passing the instance.
  • blockClass: Class added to KaTeX block.
  • Apply any other KaTeX options if needed as a regard to the docs
js
md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })

4: Examples

4.1: Inline math

To render your LaTeX equations inline, enclose them with a single dollar sign $ on each side of the equation as follows,

tex
$\sqrt{3x-1}+(1+x)^2$
$\sqrt{3x-1}+(1+x)^2$

rendered output equation as follows, 3x1+(1+x)2\sqrt{3x-1}+(1+x)^2

3: Configuration

The following list of variable are the customizable components of markdown-it-katex, adjust to your needs,

  • katex: You can change KaTeX version by passing the instance.
  • blockClass: Class added to KaTeX block.
  • Apply any other KaTeX options if needed as a regard to the docs
js
md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })

4: Examples

4.1: Inline math

To render your LaTeX equations inline, enclose them with a single dollar sign $ on each side of the equation as follows,

tex
$\sqrt{3x-1}+(1+x)^2$
$\sqrt{3x-1}+(1+x)^2$

rendered output equation as follows, 3x1+(1+x)2\sqrt{3x-1}+(1+x)^2.

4.2: Blocked math

To render blocks, use double dollar sign ($$). This mode utilizes larger symbols and centers the result as a block displayed as a <div> block in HTML output, as follows,

tex
$$
-\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
-= \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
-$$
$$
-\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
-= \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
-$$

the above block equation renders the LaTeX equation as a block with output as follows,

rωr(yωω)=(yωω){(logy)r+i=1r(1)Ir(ri+1)(logy)riωi}\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right) = \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}

5: Syntax

Math parsing in markdown is designed to comply with the "latex-in-markdown" conventions set by Pandoc,

Anything between two $ characters will be treated as TeX math. The opening $ must have a non-space character immediately to its right, while the closing $ must have a non-space character immediately to its left, and must not be followed immediately by a digit. Thus, $20,000 and $30,000 won’t parse as math. If for some reason you need to enclose text in literal $ characters, backslash-escape them and they won’t be treated as math delimiters.

  • Pandoc. “Pandoc - Pandoc User’s Guide.” Pandoc.org, pandoc.org/MANUAL.html#math. Accessed 2 Mar. 2023.

6: Supported math syntax

KaTeX is a popular, open-source math typesetting library that is based on TeX and LaTeX. It is designed to be easy to use, and to provide high-quality mathematical typesetting for web applications, refer to the following pages of the document for the full list of function support in KaTeX.

Note

Due to the large number of equations rendered on the next following pages, it might takes time to entirely load the webpage, please be patient if the webpage seems to not respond; or it could be a result of slow network connection to correctly render all the equation that causes broken formulas, refresh the page to proceed.

- +M834 80h400000v40h-400000z">+(1+x)2.

4.2: Blocked math

To render blocks, use double dollar sign ($$). This mode utilizes larger symbols and centers the result as a block displayed as a <div> block in HTML output, as follows,

tex
$$
+\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
+= \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
+$$
$$
+\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
+= \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
+$$

the above block equation renders the LaTeX equation as a block with output as follows,

rωr(yωω)=(yωω){(logy)r+i=1r(1)Ir(ri+1)(logy)riωi}\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right) = \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}

5: Syntax

Math parsing in markdown is designed to comply with the "latex-in-markdown" conventions set by Pandoc,

Anything between two $ characters will be treated as TeX math. The opening $ must have a non-space character immediately to its right, while the closing $ must have a non-space character immediately to its left, and must not be followed immediately by a digit. Thus, $20,000 and $30,000 won’t parse as math. If for some reason you need to enclose text in literal $ characters, backslash-escape them and they won’t be treated as math delimiters.

  • Pandoc. “Pandoc - Pandoc User’s Guide.” Pandoc.org, pandoc.org/MANUAL.html#math. Accessed 2 Mar. 2023.

6: Supported math syntax

KaTeX is a popular, open-source math typesetting library that is based on TeX and LaTeX. It is designed to be easy to use, and to provide high-quality mathematical typesetting for web applications, refer to the following pages of the document for the full list of function support in KaTeX.

Note

Due to the large number of equations rendered on the next following pages, it might takes time to entirely load the webpage, please be patient if the webpage seems to not respond; or it could be a result of slow network connection to correctly render all the equation that causes broken formulas, refresh the page to proceed.

+ \ No newline at end of file diff --git a/application/markdown-it-katex/support-function.html b/application/markdown-it-katex/support-function.html index 2c9d9055..fd84d3f4 100644 --- a/application/markdown-it-katex/support-function.html +++ b/application/markdown-it-katex/support-function.html @@ -5,15 +5,15 @@ KaTeX: Supported functions | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

KaTeX: Supported function

Author:Anda Toshiki
Updated:4 minutes ago
Words:3.9k
Reading:24 min

note

This is an direct shameful copy of the documentation pulled from KaTeX documentation, I do not own any of the content below on behalf of this part of the documentation, the table might be outdated as versions migrates, please also refer to KaTeX's official documentation.

This following is a list of TeX functions supported by KaTeX. It is sorted into logical groups.

There is a similar Support Table on the next page, sorted alphabetically in am more intuitive way with the lists both supported and un-supported functions, viewing both tables are suggested comprehensibly and interchangeably is highly suggested.

1: Accents

aa' a'a~\tilde{a} \tilde{a}g˚\mathring{g} \mathring{g}
aa'' a''ac~\widetilde{ac} \xlongequal{abc}

Extensible arrows all can take an optional argument in the same manner, as \xrightarrow[under]{over}.

11: Style, Color, Size, and Font

Class Assignment

  • \mathbin \mathclose \mathinner \mathop

  • \mathopen \mathord \mathpunct \mathrel

Color

F=ma\color{blue} F=ma \color{blue} F=ma

Note that KaTeX \color acts like a switch. This aligns with LaTeX and differs from MathJax. Other KaTeX color functions expect the content to be a function argument:

  • F=ma\textcolor{blue}{F=ma} \textcolor{blue}{F=ma}
  • F=ma\textcolor{#228B22}{F=ma} \textcolor{#228B22}{F=ma}
  • A\colorbox{aqua}{A} \colorbox{aqua}{A}
  • A\fcolorbox{red}{aqua}{A} \fcolorbox{red}{aqua}{A}

For color definition, KaTeX color functions will accept the standard HTML predefined color names. They will also accept an RGB argument in CSS hexa­decimal style. The "#" is optional before a six-digit specification.

Font

Ab0\mathrm{Ab0} \mathrm{Ab0}Ab0\mathbf{Ab0} \mathbf{Ab0}Ab\mathit{Ab} \mathit{Ab}
Ab0\mathnormal{Ab0} \mathnormal{Ab0}Ab0\textbf{Ab0} \textbf{Ab0}Ab\textit{Ab} \textit{Ab}
Ab0\textrm{Ab0} \textrm{Ab0}Ab0\bf Ab0 \bf Ab0Ab\it Ab \it Ab
Ab0\rm Ab0 \rm Ab0Ab0\bold{Ab0} \bold{Ab0}AB\Bbb{AB} \Bbb{AB}
Ab0\textnormal{Ab0} \textnormal{Ab0}Ab\boldsymbol{Ab} \boldsymbol{Ab}AB\mathbb{AB} \mathbb{AB}
Ab0\text{Ab0} \text{Ab0}Ab\bm{Ab} \bm{Ab}Ab0\frak{Ab0} \frak{Ab0}
Ab0\mathsf{Ab0} \mathsf{Ab0}Ab0\mathtt{Ab0} \mathtt{Ab0}Ab0\mathfrak{Ab0} \mathfrak{Ab0}
Ab0\textsf{Ab0} \textsf{Ab0}Ab0\texttt{Ab0} \texttt{Ab0}AB0\mathcal{AB0} \mathcal{AB0}
Ab0\sf Ab0 \sf Ab0Ab0\tt Ab0 \tt Ab0AB\mathscr{AB} \mathscr{AB}

One can stack font family, font weight, and font shape by using the \textXX versions of the font functions. So \textsf{\textbf{H}} will produce H\textsf{\textbf{H}}. The other versions do not stack, e.g., \mathsf{\mathbf{H}} will produce H\mathsf{\mathbf{H}}.

In cases where KaTeX fonts do not have a bold glyph, \pmb can simulate one. For example, \pmb{\mu} renders as : μ\pmb{\mu}

Size

AB\Huge AB \Huge ABAB\normalsize AB \normalsize AB
AB\huge AB \huge ABAB\small AB \small AB
AB\LARGE AB \LARGE ABAB\footnotesize AB \footnotesize AB
AB\Large AB \Large ABAB\scriptsize AB \scriptsize AB
AB\large AB \large ABAB\tiny AB \tiny AB

Style

|i=1n\displaystyle\sum_{i=1}^n \displaystyle\sum_{i=1}^n |i=1n\textstyle\sum_{i=1}^n \textstyle\sum_{i=1}^n |x\scriptstyle x \scriptstyle x         (The size of a first sub/superscript) |x\scriptscriptstyle x \scriptscriptstyle x (The size of subsequent sub/superscripts) |limx\lim\limits_x \lim\limits_x |limx\lim\nolimits_x \lim\nolimits_x |x^2\verb!x^2! \verb!x^2!

\text{…} will accept nested $…$ fragments and render them in math mode.

12: Symbols and Punctuation

% comment\dots \dotsKaTeX\KaTeX \KaTeX
%\% \%\cdots \cdotsLaTeX\LaTeX \LaTeX
#\# \#\ddots \ddotsTeX\TeX \TeX
&\& \&\ldots \ldots\nabla \nabla
_\_ \_\vdots \vdots\infty \infty
_\text{\textunderscore} \text{\textunderscore}\dotsb \dotsb\infin \infin
\text{--} \text{--}\dotsc \dotsc\checkmark \checkmark
\text{\textendash} \text{\textendash} ⁣\dotsi \dotsi\dag \dag
\text{---} \text{---}\dotsm \dotsm\dagger \dagger
\text{\textemdash} \text{\textemdash}\dotso \dotso\text{\textdagger} \text{\textdagger}
~\text{\textasciitilde} \text{\textasciitilde}\sdot \sdot\ddag \ddag
` `\mathellipsis \mathellipsis\ddagger \ddagger
\text{\textquoteleft} text{\textquoteleft}\text{\textellipsis} \text{\textellipsis}\text{\textdaggerdbl} \text{\textdaggerdbl}
\lq \lq\Box \Box\Dagger \Dagger
\text{\textquoteright} \text{\textquoteright}\square \square\angle \angle
\rq \rq\blacksquare \blacksquare\measuredangle \measuredangle
\text{\textquotedblleft} \text{\textquotedblleft}\triangle \triangle\sphericalangle \sphericalangle
"" "\triangledown \triangledown\top \top
\text{\textquotedblright} \text{\textquotedblright}\triangleleft \triangleleft\bot \bot
 ⁣:\colon \colon\triangleright \triangleright$\$ \$
\backprime \backprime\bigtriangledown \bigtriangledown$\text{\textdollar} \text{\textdollar}
\prime \prime\bigtriangleup \bigtriangleup£\pounds \pounds
<\text{\textless} \text{\textless}\blacktriangle \blacktriangle£\mathsterling \mathsterling
>\text{\textgreater} \text{\textgreater}\blacktriangledown \blacktriangledown£\text{\textsterling} \text{\textsterling}
|\text{\textbar} \text{\textbar}\blacktriangleleft \blacktriangleleft¥\yen \yen
\text{\textbardbl} \text{\textbardbl}\blacktriangleright \blacktriangleright\surd \surd
{\text{\textbraceleft} \text{\textbraceleft}\diamond \diamond°\degree \degree
}\text{\textbraceright} \text{\textbraceright}\Diamond \Diamond°\text{\textdegree} \text{\textdegree}
\text{\P} \text{\P}\lozenge \lozenge\mho \mho
§\text{\S} \text{\S}\blacklozenge \blacklozenge\diagdown \diagdown
§\text{\sect} \text{\sect}\star \star\diagup \diagup
©\copyright \copyright\bigstar \bigstar\flat \flat
®\circledR \circledR\clubsuit \clubsuit\natural \natural
®\text{\textregistered} \text{\textregistered}\clubs \clubs\sharp \sharp
\circledS \circledS\diamondsuit \diamondsuit\heartsuit \heartsuit
a\text{\textcircled a} \text{\textcircled a}\diamonds \diamonds\hearts \hearts
\maltese \maltese\spadesuit \spadesuit\spades \spades

Direct Input: £¥!£ ¥ ∇ ∞ · ∠ ∡ ∢ ♠ ♡ ♢ ♣ ♭ ♮ ♯ ✓ … ⋮ ⋯ ⋱ !

13: Units

In KaTeX, units are proportioned as they are in TeX. KaTeX units are different than CSS units.

KaTeX UnitValueKaTeX UnitValue
emCSS embp1/72​ inch × F × G
exCSS expc12 KaTeX pt
mu1/18 CSS emdd1238/1157​ KaTeX pt
pt1/72.27 inch × F × Gcc14856/1157 KaTeX pt
mm1 mm × F × Gnd685/642 KaTeX pt
cm1 cm × F × Gnc1370/107​ KaTeX pt
in1 inch × F × Gsp1/65536 KaTeX pt

where:

  • F = (font size of surrounding HTML text)/(10 pt)

  • G = 1.21 by default, because KaTeX font-size is normally 1.21 × the surrounding font size. This value can be overridden by the CSS of an HTML page.

The effect of style and size:

Unittextstylescriptscripthuge
em or ex\rule{1em}{1em}\scriptscriptstyle\rule{1em}{1em}\huge\rule{1em}{1em}
mu\rule{18mu}{18mu}\scriptscriptstyle\rule{18mu}{18mu}\huge\rule{18mu}{18mu}
others\rule{10pt}{10pt}\scriptscriptstyle\rule{10pt}{10pt}\huge\rule{10pt}{10pt}
+ \ No newline at end of file diff --git a/application/markdown-it-katex/support-table.html b/application/markdown-it-katex/support-table.html index 50965ec5..280a0a61 100644 --- a/application/markdown-it-katex/support-table.html +++ b/application/markdown-it-katex/support-table.html @@ -5,15 +5,15 @@ KaTeX: Support table | Toshiki's Note - + - + - + - + @@ -36,7 +36,7 @@ -
Skip to content

KaTeX: Support table

Author:Anda Toshiki
Updated:4 minutes ago
Words:5.8k
Reading:36 min

note

This is an direct shameful copy of the documentation pulled from KaTeX documentation, I do not own any of the content below on behalf of this part of the documentation, the table might be outdated as versions migrates, please also refer to KaTeX's official documentation.

Symbols

Symbol/FunctionRenderedSource or Comment
!n!n!n!
\!a ⁣ba\!ba\!b
#y2\def\bar#1{#1^2} \bar{y}\def\bar#1{#1^2} \bar{y}
\##\#
%%this is a comment
\%%\%
&abcd\begin{matrix} a & b\cr c & d \end{matrix}\begin{matrix}
   a & b \\
   c & d
\end{matrix}
\&&\&
''
\'aˊ\text{\'{a}}\text{\'{a}}
(((
)))
\(…\)ab\text{\(\frac a b\)}\text{\(\frac a b\)}
\a ba\ ba\ b
\"a¨\text{\"{a}}\text{\"{a}}
\$$\text{\textdollar}
\,aba\,\,{b}a\,\,{b}
\.a˙\text{\.{a}}\text{\.{a}}
\:aba\:\:{b}a\:\:{b}
\;a    ba\;\;{b}a\;\;{b}
_xix_ix_i
\__\_
\`aˋ\text{\`{a}}\text{\'{a}}
<<<
\=aˉ\text{\={a}}\text{\\={a}}
>>>
\>aba\>\>{b}a\>\>{b}
[[[
]]]
{a{a}{a}
}a{a}{a}
\{{\{
\}}\}
|\vert
\|\Vert
~no no no breaks\text{no~no~no~breaks}\text{no~no~no~breaks}
\~a˜\text{\~{a}}\text{\\~{a}}
\\abcd\begin{matrix} a & b\\ c & d\end{matrix}\begin{matrix}
   a & b \\
   c & d
\end{matrix}
^xix^ix^i
\^aˆ\text{\^{a}}\text{\\^{a}}

A

Symbol/FunctionRenderedSource or Comment
\AAA˚\text{\AA}\text{\AA}
\aaa˚\text{\aa}\text{\aa}
\aboveab+1{a \above{2pt} b+1}{a \above{2pt} b+1}
\abovewithdelimsNot supported
\acuteeˊ\acute e\acute e
\AEÆ\text{\AE}\text{\AE}
\aeæ\text{\ae}\text{\ae}
\alef\alef
\alefsym\alefsym
\aleph\aleph
Not supportedsee {aligned}
a=b+cd+e=f\begin{aligned}a&=b+c\\d+e&=f\end{aligned}\begin{aligned}
   a&=b+c \\
   d+e&=f
\end{aligned}
Not supportedsee {alignedat}
10x+3y=23x+13y=4\begin{alignedat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignedat}\begin{alignedat}{2}
   10&x+ &3&y = 2 \\
    3&x+&13&y = 4
\end{alignedat}
\allowbreak
\AlphaA\Alpha
\alphaα\alpha
\amalg⨿\amalg
\And&\And
\andNot supportedDeprecated
\angNot supportedDeprecated
\anglNot supported
\angle\angle
\approx\approx
\approxeq\approxeq
\arccosarccos\arccos
\arcctgarcctg\arcctg
\arcsinarcsin\arcsin
\arctanarctan\arctan
\arctgarctg\arctg
\argarg\arg
\argmaxarg max\argmax
\argminarg min\argmin
abcd\begin{array}{cc}a&b\\c&d\end{array}\begin{array}{cc}
   a & b \\
   c & d
\end{array}
\arrayNot supportedsee {array}
\arraystretchabcd\def\arraystretch{1.5}\begin{array}{cc}a&b\\c&d\end{array}\def\arraystretch{1.5}
\begin{array}{cc}
   a & b \\
   c & d
\end{array}
\ArrowvertNot supported
\arrowvertNot supported
\ast\ast
\asymp\asymp
\atopab{a \atop b}{a \atop b}
\atopwithdelimsNot supported

B

| Symbol/Function | Rendered | Source or Comment | | :------------------ | :-------------------------------------------------- | :------------------------------------------------------------------------------------------------ | ------ | | \backepsilon | \backepsilon | | | \backprime | \backprime | | | \backsim | \backsim | | | \backsimeq | \backsimeq | | | \backslash | \\backslash | | | \bar | yˉ\bar{y} | \bar{y} | | \barwedge | \barwedge | | | \Bbb | ABC\Bbb{ABC} | \Bbb{ABC}
KaTeX supports A-Z & k | | \Bbbk | k\Bbbk | | | \bbox | Not supported | | | \bcancel | 5\bcancel{5} | \bcancel{5} | | \because | \because | | | \begin | abcd\begin{matrix} a & b\\ c & d\end{matrix} | \begin{matrix}
   a & b \\
   c & d
\end{matrix} | | \begingroup | \begingroup a} | \begingroup a} | | \Beta | B\Beta | | | \beta | β\beta | | | \beth | \beth | | | \between | \between | | | \bf | AaBb12\bf AaBb12 | \bf AaBb12 | | \bfseries | Not supported | | | \big | ()\big(\big) | \big(\big) | | \Big | ()\Big(\Big) | \Big(\Big) | | \bigcap | \bigcap | | | \bigcirc | \bigcirc | | | \bigcup | \bigcup | | | \bigg | ()\bigg(\bigg) | \bigg(\bigg) | | \Bigg | ()\Bigg(\Bigg) | \Bigg(\Bigg) | | \biggl | (\biggl( | \biggl( | | \Biggl | (\Biggl( | \Biggl( | | \biggm | \biggm\vert

Skip to content

KaTeX: Support table

Author:Anda Toshiki
Updated:2 minutes ago
Words:5.8k
Reading:36 min

note

This is an direct shameful copy of the documentation pulled from KaTeX documentation, I do not own any of the content below on behalf of this part of the documentation, the table might be outdated as versions migrates, please also refer to KaTeX's official documentation.

Symbols

Symbol/FunctionRenderedSource or Comment
!n!n!n!
\!a ⁣ba\!ba\!b
#y2\def\bar#1{#1^2} \bar{y}\def\bar#1{#1^2} \bar{y}
\##\#
%%this is a comment
\%%\%
&abcd\begin{matrix} a & b\cr c & d \end{matrix}\begin{matrix}
   a & b \\
   c & d
\end{matrix}
\&&\&
''
\'aˊ\text{\'{a}}\text{\'{a}}
(((
)))
\(…\)ab\text{\(\frac a b\)}\text{\(\frac a b\)}
\a ba\ ba\ b
\"a¨\text{\"{a}}\text{\"{a}}
\$$\text{\textdollar}
\,aba\,\,{b}a\,\,{b}
\.a˙\text{\.{a}}\text{\.{a}}
\:aba\:\:{b}a\:\:{b}
\;a    ba\;\;{b}a\;\;{b}
_xix_ix_i
\__\_
\`aˋ\text{\`{a}}\text{\'{a}}
<<<
\=aˉ\text{\={a}}\text{\\={a}}
>>>
\>aba\>\>{b}a\>\>{b}
[[[
]]]
{a{a}{a}
}a{a}{a}
\{{\{
\}}\}
|\vert
\|\Vert
~no no no breaks\text{no~no~no~breaks}\text{no~no~no~breaks}
\~a˜\text{\~{a}}\text{\\~{a}}
\\abcd\begin{matrix} a & b\\ c & d\end{matrix}\begin{matrix}
   a & b \\
   c & d
\end{matrix}
^xix^ix^i
\^aˆ\text{\^{a}}\text{\\^{a}}

A

Symbol/FunctionRenderedSource or Comment
\AAA˚\text{\AA}\text{\AA}
\aaa˚\text{\aa}\text{\aa}
\aboveab+1{a \above{2pt} b+1}{a \above{2pt} b+1}
\abovewithdelimsNot supported
\acuteeˊ\acute e\acute e
\AEÆ\text{\AE}\text{\AE}
\aeæ\text{\ae}\text{\ae}
\alef\alef
\alefsym\alefsym
\aleph\aleph
Not supportedsee {aligned}
a=b+cd+e=f\begin{aligned}a&=b+c\\d+e&=f\end{aligned}\begin{aligned}
   a&=b+c \\
   d+e&=f
\end{aligned}
Not supportedsee {alignedat}
10x+3y=23x+13y=4\begin{alignedat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignedat}\begin{alignedat}{2}
   10&x+ &3&y = 2 \\
    3&x+&13&y = 4
\end{alignedat}
\allowbreak
\AlphaA\Alpha
\alphaα\alpha
\amalg⨿\amalg
\And&\And
\andNot supportedDeprecated
\angNot supportedDeprecated
\anglNot supported
\angle\angle
\approx\approx
\approxeq\approxeq
\arccosarccos\arccos
\arcctgarcctg\arcctg
\arcsinarcsin\arcsin
\arctanarctan\arctan
\arctgarctg\arctg
\argarg\arg
\argmaxarg max\argmax
\argminarg min\argmin
abcd\begin{array}{cc}a&b\\c&d\end{array}\begin{array}{cc}
   a & b \\
   c & d
\end{array}
\arrayNot supportedsee {array}
\arraystretchabcd\def\arraystretch{1.5}\begin{array}{cc}a&b\\c&d\end{array}\def\arraystretch{1.5}
\begin{array}{cc}
   a & b \\
   c & d
\end{array}
\ArrowvertNot supported
\arrowvertNot supported
\ast\ast
\asymp\asymp
\atopab{a \atop b}{a \atop b}
\atopwithdelimsNot supported

B

| Symbol/Function | Rendered | Source or Comment | | :------------------ | :-------------------------------------------------- | :------------------------------------------------------------------------------------------------ | ------ | | \backepsilon | \backepsilon | | | \backprime | \backprime | | | \backsim | \backsim | | | \backsimeq | \backsimeq | | | \backslash | \\backslash | | | \bar | yˉ\bar{y} | \bar{y} | | \barwedge | \barwedge | | | \Bbb | ABC\Bbb{ABC} | \Bbb{ABC}
KaTeX supports A-Z & k | | \Bbbk | k\Bbbk | | | \bbox | Not supported | | | \bcancel | 5\bcancel{5} | \bcancel{5} | | \because | \because | | | \begin | abcd\begin{matrix} a & b\\ c & d\end{matrix} | \begin{matrix}
   a & b \\
   c & d
\end{matrix} | | \begingroup | \begingroup a} | \begingroup a} | | \Beta | B\Beta | | | \beta | β\beta | | | \beth | \beth | | | \between | \between | | | \bf | AaBb12\bf AaBb12 | \bf AaBb12 | | \bfseries | Not supported | | | \big | ()\big(\big) | \big(\big) | | \Big | ()\Big(\Big) | \Big(\Big) | | \bigcap | \bigcap | | | \bigcirc | \bigcirc | | | \bigcup | \bigcup | | | \bigg | ()\bigg(\bigg) | \bigg(\bigg) | | \Bigg | ()\Bigg(\Bigg) | \Bigg(\Bigg) | | \biggl | (\biggl( | \biggl( | | \Biggl | (\Biggl( | \Biggl( | | \biggm | \biggm\vert | \biggm\vert | | \Biggm | \Biggm\vert

\xtwoheadrightarrow{abc}

YZ

Symbol/FunctionRenderedSource or Comment
\yen¥\yen
\ZZ\Z
\ZetaZ\Zeta
\zetaζ\zeta
- + 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z">\xtwoheadrightarrow{abc}

YZ

Symbol/FunctionRenderedSource or Comment
\yen¥\yen
\ZZ\Z
\ZetaZ\Zeta
\zetaζ\zeta
+ \ No newline at end of file diff --git a/application/markdown-it-katex/tips.html b/application/markdown-it-katex/tips.html index 226572d1..80501cef 100644 --- a/application/markdown-it-katex/tips.html +++ b/application/markdown-it-katex/tips.html @@ -5,15 +5,15 @@ Tips to Use markdown-it-katex | Toshiki's Note - + - + - + - + @@ -36,104 +36,104 @@ -
Skip to content

Tips & Hacks

Author:Anda Toshiki
Updated:4 minutes ago
Words:1.2k
Reading:7 min

1: Responsive KaTeX Styling

1.1: Issue background

KaTeX works out of the box on large screen devices such as laptops and desktop computers. But as KaTeX's built-in does not support responsiveness on it's default stylings, hence KaTeX equations might overflow out of the default width of the default application containers on small-screened mobile devices as you can see in the following image in the dev tool of chrome, when the dimension of the webpage is set to responsive or under a certain fixed device dimension, the equations rendered in KaTeX overflows out of the viewport as inspected in blue hightlight.

katex overflowing on small screen devices
◎ katex overflowing on small screen devices

This inevitably causes the viewport to break and extends the default width for KaTeX equations <div> to fit, users will be required to manually scroll right in order to view the full equation consequently as follows,

katex overflowing with labels annotated
◎ katex overflowing with labels annotated

The above situation is undoubtedly annoying for user experiences while reading documentation, consider at what scenarios users have to scroll, scroll and scroll only for viewing a single long-blocked equation, who would want to read such a text, right? But don't worry we have a simple fix for this situation via by several line of css.

1.2: Temporary solution

If you happened to search over KaTeX's official repo issue tracker on GitHub, there are several user-made css tweaks hack already, the fix is simple by adjusting the overflows of both x and y axes of the KaTeX render <div> blocks. The katex-display > .katex selector targets the child element of the .katex-display class that has the .katex class. This is the element that contains the KaTeX math expression. The first block of styles is mostly concerned with making sure that the KaTeX expression doesn't overflow its container and can be scrolled horizontally if needed. The second block of styles sets the font and line-height for the KaTeX expression and makes sure that its text is properly indented.

But, the issue here is, the overflowing issue is resolved on the webpage, but the style itself left with a slight whitish "box" at the crossing corner of both horizontal as well as vertical scrollbar tracks, this might not be so explicit in the light mode of the webpage, but when it turns to dark mode, the box become annoying. Some people might say it's an easy tweak via setting the display property of the "box" element to display: none; to directly remove the box out of the page, this is a smart approach; however, while the box is gone, the two crossing tracks is going to form an untouched invisible box again against two bars without color. Thus, neither ways seems to perfectly solve the problem.

1.3: Finding solution

After running a quick research on Google, I found a simple hack tweak used in a theme of VuePress, vuepress-theme-hope on GitHub, the theme both integrate with KaTeX and MathJax for math supports.

Under the styles directory of the repository, several line of scss styles came across my eyes,

KaTeX tweak fix styles in theme
◎ KaTeX tweak fix styles in theme

this scss lines only add a horizontal trackbar at the bottom of each overflowing equation while maximizing the vertical height of the equation, when user is on a small screened device as follows,

Horizontal scrollbar of equations on small screens
◎ Horizontal scrollbar of equations on small screen

Consequently, the fix is easy.

1.4: Solution

If you are running a documentation site like this version controlled via Node, especially VitePress without native scss supports, your fix would be installing scss support globally across the project, then add the scss styles and finally import the stylesheets to take effect globally.

Install global scss support using your favored package manager.

sh
$ npm install -D scss
$ npm install -D scss
sh
$ yarn add --dev scss
$ yarn add --dev scss
sh
$ pnpm add -D scss
$ pnpm add -D scss

Then in your scss stylesheets, add the following and link or import them to your global styles, you should be off to go with a complete fix-up for KaTeX.

scss
...
+    
Skip to content

Tips & Hacks

Author:Anda Toshiki
Updated:2 minutes ago
Words:1.2k
Reading:7 min

1: Responsive KaTeX Styling

1.1: Issue background

KaTeX works out of the box on large screen devices such as laptops and desktop computers. But as KaTeX's built-in does not support responsiveness on it's default stylings, hence KaTeX equations might overflow out of the default width of the default application containers on small-screened mobile devices as you can see in the following image in the dev tool of chrome, when the dimension of the webpage is set to responsive or under a certain fixed device dimension, the equations rendered in KaTeX overflows out of the viewport as inspected in blue hightlight.

katex overflowing on small screen devices
◎ katex overflowing on small screen devices

This inevitably causes the viewport to break and extends the default width for KaTeX equations <div> to fit, users will be required to manually scroll right in order to view the full equation consequently as follows,

katex overflowing with labels annotated
◎ katex overflowing with labels annotated

The above situation is undoubtedly annoying for user experiences while reading documentation, consider at what scenarios users have to scroll, scroll and scroll only for viewing a single long-blocked equation, who would want to read such a text, right? But don't worry we have a simple fix for this situation via by several line of css.

1.2: Temporary solution

If you happened to search over KaTeX's official repo issue tracker on GitHub, there are several user-made css tweaks hack already, the fix is simple by adjusting the overflows of both x and y axes of the KaTeX render <div> blocks. The katex-display > .katex selector targets the child element of the .katex-display class that has the .katex class. This is the element that contains the KaTeX math expression. The first block of styles is mostly concerned with making sure that the KaTeX expression doesn't overflow its container and can be scrolled horizontally if needed. The second block of styles sets the font and line-height for the KaTeX expression and makes sure that its text is properly indented.

@preview

But, the issue here is, the overflowing issue is resolved on the webpage, but the style itself left with a slight whitish "box" at the crossing corner of both horizontal as well as vertical scrollbar tracks, this might not be so explicit in the light mode of the webpage, but when it turns to dark mode, the box become annoying. Some people might say it's an easy tweak via setting the display property of the "box" element to display: none; to directly remove the box out of the page, this is a smart approach; however, while the box is gone, the two crossing tracks is going to form an untouched invisible box again against two bars without color. Thus, neither ways seems to perfectly solve the problem.

1.3: Finding solution

After running a quick research on Google, I found a simple hack tweak used in a theme of VuePress, vuepress-theme-hope on GitHub, the theme both integrate with KaTeX and MathJax for math supports.

@preview

Under the styles directory of the repository, several line of scss styles came across my eyes,

KaTeX tweak fix styles in theme
◎ KaTeX tweak fix styles in theme

this scss lines only add a horizontal trackbar at the bottom of each overflowing equation while maximizing the vertical height of the equation, when user is on a small screened device as follows,

Horizontal scrollbar of equations on small screens
◎ Horizontal scrollbar of equations on small screen

Consequently, the fix is easy.

1.4: Solution

If you are running a documentation site like this version controlled via Node, especially VitePress without native scss supports, your fix would be installing scss support globally across the project, then add the scss styles and finally import the stylesheets to take effect globally.

Install global scss support using your favored package manager.

sh
$ npm install -D scss
$ npm install -D scss
sh
$ yarn add --dev scss
$ yarn add --dev scss
sh
$ pnpm add -D scss
$ pnpm add -D scss

Then in your scss stylesheets, add the following and link or import them to your global styles, you should be off to go with a complete fix-up for KaTeX.

scss
...
 
-// katex responsiveness fix
-.katex {
-  font-size: 1.05em;
-  direction: ltr;
-}
+// katex responsiveness fix
+.katex {
+  font-size: 1.05em;
+  direction: ltr;
+}
 
-.katex-display {
-  overflow: auto hidden;
-  -webkit-overflow-scrolling: touch;
-  padding-top: 0.2em;
-  padding-bottom: 0.2em;
+.katex-display {
+  overflow: auto hidden;
+  -webkit-overflow-scrolling: touch;
+  padding-top: 0.2em;
+  padding-bottom: 0.2em;
 
-  &::-webkit-scrollbar {
-    height: 3px;
-  }
+  &::-webkit-scrollbar {
+    height: 3px;
+  }
 
-  .katex {
-    font-size: 1.21em;
-  }
-}
+  .katex {
+    font-size: 1.21em;
+  }
+}
 
-.katex-error {
-  color: #f00;
-}
-// katex responsiveness fix ends
+.katex-error {
+  color: #f00;
+}
+// katex responsiveness fix ends
 
-...
...
+...
...
 
-// katex responsiveness fix
-.katex {
-  font-size: 1.05em;
-  direction: ltr;
-}
+// katex responsiveness fix
+.katex {
+  font-size: 1.05em;
+  direction: ltr;
+}
 
-.katex-display {
-  overflow: auto hidden;
-  -webkit-overflow-scrolling: touch;
-  padding-top: 0.2em;
-  padding-bottom: 0.2em;
+.katex-display {
+  overflow: auto hidden;
+  -webkit-overflow-scrolling: touch;
+  padding-top: 0.2em;
+  padding-bottom: 0.2em;
 
-  &::-webkit-scrollbar {
-    height: 3px;
-  }
+  &::-webkit-scrollbar {
+    height: 3px;
+  }
 
-  .katex {
-    font-size: 1.21em;
-  }
-}
+  .katex {
+    font-size: 1.21em;
+  }
+}
 
-.katex-error {
-  color: #f00;
-}
-// katex responsiveness fix ends
+.katex-error {
+  color: #f00;
+}
+// katex responsiveness fix ends
 
-...

Next, import your styles globally to take effect,

scss
@import '<your-scss-file>.scss';
@import '<your-scss-file>.scss';

1.4.1: Fix Explanation

The first section sets the base styles for all KaTeX elements by increasing the font size slightly and ensuring that the text direction is left to right.

The second section of code targets the KaTeX display elements specifically. This section adds a bit of padding to the top and bottom of the display elements and sets overflow to auto hidden, which allows the content to scroll inside the container horizontally if it overflows the container's width. The -webkit-overflow-scrolling property is added to ensure smooth scrolling on mobile devices.

Additionally, this section contains a nested .katex selector, which increases the font size of the KaTeX elements within the display element.

The third section targets the .katex-error class and sets the color to red to indicate that there is an error in rendering the LaTeX expression.

1.5: What if I Don't Have SCSS?

If you do not have native scss support for your site, such as a static HTML based documentation site or content management site builder such as Wiki.JS that works as an SaaS which only allows users to apply custom stylesheets within slots provided and make effects, you could use some scss to css converter online with options follows,

to precompile from source scss into normal css styles and use them based on your needs, below are auto-generated compiled css, ONLY take it as reference, I do not guarantee the usability.

css
.katex {
-    font-size: 1.05em;
-    direction: ltr;
-}
+...

Next, import your styles globally to take effect,

scss
@import '<your-scss-file>.scss';
@import '<your-scss-file>.scss';

1.4.1: Fix Explanation

The first section sets the base styles for all KaTeX elements by increasing the font size slightly and ensuring that the text direction is left to right.

The second section of code targets the KaTeX display elements specifically. This section adds a bit of padding to the top and bottom of the display elements and sets overflow to auto hidden, which allows the content to scroll inside the container horizontally if it overflows the container's width. The -webkit-overflow-scrolling property is added to ensure smooth scrolling on mobile devices.

Additionally, this section contains a nested .katex selector, which increases the font size of the KaTeX elements within the display element.

The third section targets the .katex-error class and sets the color to red to indicate that there is an error in rendering the LaTeX expression.

1.5: What if I Don't Have SCSS?

If you do not have native scss support for your site, such as a static HTML based documentation site or content management site builder such as Wiki.JS that works as an SaaS which only allows users to apply custom stylesheets within slots provided and make effects, you could use some scss to css converter online with options follows,

to precompile from source scss into normal css styles and use them based on your needs, below are auto-generated compiled css, ONLY take it as reference, I do not guarantee the usability.

css
.katex {
+    font-size: 1.05em;
+    direction: ltr;
+}
 
-.katex-display {
-    overflow: auto hidden;
-    -webkit-overflow-scrolling: touch;
-    padding-top: 0.2em;
-    padding-bottom: 0.2em;
-}
-.katex-display::-webkit-scrollbar {
-    height: 3px;
-}
-.katex-display .katex {
-    font-size: 1.21em;
-}
+.katex-display {
+    overflow: auto hidden;
+    -webkit-overflow-scrolling: touch;
+    padding-top: 0.2em;
+    padding-bottom: 0.2em;
+}
+.katex-display::-webkit-scrollbar {
+    height: 3px;
+}
+.katex-display .katex {
+    font-size: 1.21em;
+}
 
-.katex-error {
-    color: #f00;
-}
.katex {
-    font-size: 1.05em;
-    direction: ltr;
-}
+.katex-error {
+    color: #f00;
+}
.katex {
+    font-size: 1.05em;
+    direction: ltr;
+}
 
-.katex-display {
-    overflow: auto hidden;
-    -webkit-overflow-scrolling: touch;
-    padding-top: 0.2em;
-    padding-bottom: 0.2em;
-}
-.katex-display::-webkit-scrollbar {
-    height: 3px;
-}
-.katex-display .katex {
-    font-size: 1.21em;
-}
+.katex-display {
+    overflow: auto hidden;
+    -webkit-overflow-scrolling: touch;
+    padding-top: 0.2em;
+    padding-bottom: 0.2em;
+}
+.katex-display::-webkit-scrollbar {
+    height: 3px;
+}
+.katex-display .katex {
+    font-size: 1.21em;
+}
 
-.katex-error {
-    color: #f00;
-}

To be continued.

- +.katex-error { + color: #f00; +}

To be continued.

+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/api/annotations.html b/application/vitepress-plugin-shiki-twoslash/api/annotations.html index 7515d759..41864470 100644 --- a/application/vitepress-plugin-shiki-twoslash/api/annotations.html +++ b/application/vitepress-plugin-shiki-twoslash/api/annotations.html @@ -5,15 +5,15 @@ Meta Annotations | Toshiki's Note - + - + - + - + @@ -36,101 +36,101 @@ -
Skip to content

Queries

Author:Anda Toshiki
Updated:4 minutes ago
Words:541
Reading:3 min

Sometimes the thing you want to say is about the code, annotations provide a way to provide outside commentary on your code.

@annotate: [left|right] [overrides] - [text]

Annotate has a lot more controls than most of the other Twoslash commands, because each use of it probably needs to feel a bit different. Here's an example based on the TypeScript home page, click it to get it running so we can talk about what it does:

ts
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}
+
Skip to content

Queries

Author:Anda Toshiki
Updated:2 minutes ago
Words:541
Reading:3 min

Sometimes the thing you want to say is about the code, annotations provide a way to provide outside commentary on your code.

@annotate: [left|right] [overrides] - [text]

Annotate has a lot more controls than most of the other Twoslash commands, because each use of it probably needs to feel a bit different. Here's an example based on the TypeScript home page, click it to get it running so we can talk about what it does:

ts
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}

Discovered a typo, the param is arr, not orr!

-
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}
+
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}

Discovered a typo, the param is arr, not orr!

-
md
```ts twoslash
-// @errors: 2304
-// @strict: false
+
md
```ts twoslash
+// @errors: 2304
+// @strict: false
 
-function compact(arr) {
-    if (orr.length > 10) return arr.trim(0, 10)
-    return arr
-}
-// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
-```
```ts twoslash
-// @errors: 2304
-// @strict: false
+function compact(arr) {
+    if (orr.length > 10) return arr.trim(0, 10)
+    return arr
+}
+// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
+```
```ts twoslash
+// @errors: 2304
+// @strict: false
 
-function compact(arr) {
-    if (orr.length > 10) return arr.trim(0, 10)
-    return arr
-}
-// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
-```

First up, cool — it adds some text to the left hand side of the code. It features quite a few different options, so lets go through them one by one:

  • left or right: It's currently left. It's worth noting the arrow flips also, and 90deg isn't a great option. Let's look at that next.

  • { "arrrowRot": "90deg 8px 27px" } - This JSON object is used to manipulate the annotation, you have 3 controls for arrow positioning and rotation: degrees x y. I recommend keeping those in degrees and px, but it's your life. These are overrides from defaults which are okay, but not really something you ever want to ship.

  • { "textDegree": "3deg" } - Rotates the text, you probably want something between -3deg and 3deg. Optional, defaults to 0.

  • { "top": "0rem" } - Sets the y coordinates for the annotation relative to the code sample, if it's not included then it becomes [lineNum]rem.

What's not included in this sample is flipped, which can be used to flip the arrow's orientation. Here's some examples:

A horizontal right example:

ts
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}
+function compact(arr) { + if (orr.length > 10) return arr.trim(0, 10) + return arr +} +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr! +```

First up, cool — it adds some text to the left hand side of the code. It features quite a few different options, so lets go through them one by one:

  • left or right: It's currently left. It's worth noting the arrow flips also, and 90deg isn't a great option. Let's look at that next.

  • { "arrrowRot": "90deg 8px 27px" } - This JSON object is used to manipulate the annotation, you have 3 controls for arrow positioning and rotation: degrees x y. I recommend keeping those in degrees and px, but it's your life. These are overrides from defaults which are okay, but not really something you ever want to ship.

  • { "textDegree": "3deg" } - Rotates the text, you probably want something between -3deg and 3deg. Optional, defaults to 0.

  • { "top": "0rem" } - Sets the y coordinates for the annotation relative to the code sample, if it's not included then it becomes [lineNum]rem.

What's not included in this sample is flipped, which can be used to flip the arrow's orientation. Here's some examples:

A horizontal right example:

ts
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}

Discovered a typo, the param is arr, not orr!

-
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}
+
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}

Discovered a typo, the param is arr, not orr!

-
md
```ts twoslash
-// @errors: 2304
-// @strict: false
+
md
```ts twoslash
+// @errors: 2304
+// @strict: false
 
-function compact(arr) {
-    if (orr.length > 10) return arr.trim(0, 10)
-    return arr
-}
-// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
-```
```ts twoslash
-// @errors: 2304
-// @strict: false
+function compact(arr) {
+    if (orr.length > 10) return arr.trim(0, 10)
+    return arr
+}
+// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
+```
```ts twoslash
+// @errors: 2304
+// @strict: false
 
-function compact(arr) {
-    if (orr.length > 10) return arr.trim(0, 10)
-    return arr
-}
-// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
-```

Upside down arrow pointing at the error, using flipped to re-flip the arrow:

ts
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}
+function compact(arr) { + if (orr.length > 10) return arr.trim(0, 10) + return arr +} +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr! +```

Upside down arrow pointing at the error, using flipped to re-flip the arrow:

ts
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}

Discovered a typo, the param is arr, not orr!

-
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}
+
ts
function compact(arr) {
if (.length > 10) return arr.trim(0, 10)
Cannot find name 'orr'.2304Cannot find name 'orr'.
return arr
}

Discovered a typo, the param is arr, not orr!

-
md
```ts twoslash
-// @errors: 2304
-// @strict: false
+
md
```ts twoslash
+// @errors: 2304
+// @strict: false
 
-function compact(arr) {
-    if (orr.length > 10) return arr.trim(0, 10)
-    return arr
-}
-// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
-```
```ts twoslash
-// @errors: 2304
-// @strict: false
+function compact(arr) {
+    if (orr.length > 10) return arr.trim(0, 10)
+    return arr
+}
+// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
+```
```ts twoslash
+// @errors: 2304
+// @strict: false
 
-function compact(arr) {
-    if (orr.length > 10) return arr.trim(0, 10)
-    return arr
-}
-// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
-```
- +function compact(arr) { + if (orr.length > 10) return arr.trim(0, 10) + return arr +} +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr! +```
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/api/cutting.html b/application/vitepress-plugin-shiki-twoslash/api/cutting.html index dc3884bd..d751c48a 100644 --- a/application/vitepress-plugin-shiki-twoslash/api/cutting.html +++ b/application/vitepress-plugin-shiki-twoslash/api/cutting.html @@ -5,15 +5,15 @@ Cutting | Toshiki's Note - + - + - + - + @@ -36,52 +36,52 @@ -
Skip to content

Cutting

Author:Anda Toshiki
Updated:4 minutes ago
Words:242
Reading:1 min

Every Twoslash code example needs to be a complete TypeScript program so it can compile. Quite often to make it compile, there is a bunch of code which isn't relevant to the user. This can be extracted out of the code examples via cut comments.

---cut---

Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the ---cut---.

ts
ts
console.log(level)
ts
console.log(level)
md
```ts twoslash
-const level: string = 'Danger'
-// ---cut---
-console.log(level)
-```
```ts twoslash
-const level: string = 'Danger'
-// ---cut---
-console.log(level)
-```

Cutting even works across multiple files. This is why // @filename: [file] is specifically the only Twoslash command which is not removed, because if it's not relevant it can be ---cut--- away.

ts
ts
import { helloWorld } from './a'
console.log(helloWorld)
ts
import { helloWorld } from './a'
console.log(helloWorld)
md
```ts twoslash
-// @filename: a.ts
-export const helloWorld: string = 'Hi'
+    
Skip to content

Cutting

Author:Anda Toshiki
Updated:2 minutes ago
Words:242
Reading:1 min

Every Twoslash code example needs to be a complete TypeScript program so it can compile. Quite often to make it compile, there is a bunch of code which isn't relevant to the user. This can be extracted out of the code examples via cut comments.

---cut---

Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the ---cut---.

ts
ts
console.log(level)
ts
console.log(level)
md
```ts twoslash
+const level: string = 'Danger'
+// ---cut---
+console.log(level)
+```
```ts twoslash
+const level: string = 'Danger'
+// ---cut---
+console.log(level)
+```

Cutting even works across multiple files. This is why // @filename: [file] is specifically the only Twoslash command which is not removed, because if it's not relevant it can be ---cut--- away.

ts
ts
import { helloWorld } from './a'
console.log(helloWorld)
ts
import { helloWorld } from './a'
console.log(helloWorld)
md
```ts twoslash
+// @filename: a.ts
+export const helloWorld: string = 'Hi'
 
-// @filename: b.ts
-// ---cut---
-import { helloWorld } from './a'
-console.log(helloWorld)
-```
```ts twoslash
-// @filename: a.ts
-export const helloWorld: string = 'Hi'
+// @filename: b.ts
+// ---cut---
+import { helloWorld } from './a'
+console.log(helloWorld)
+```
```ts twoslash
+// @filename: a.ts
+export const helloWorld: string = 'Hi'
 
-// @filename: b.ts
-// ---cut---
-import { helloWorld } from './a'
-console.log(helloWorld)
-```

---cut-after---

The sibling to ---cut---, which trims anything after the sigil:

tsx
tsx
<Container>
<ImportantComponent />
</Container>
tsx
<Container>
<ImportantComponent />
</Container>
md
```tsx twoslash
-const Page = () => (
-    // ---cut---
-    <Container>
-        <ImportantComponent />
-    </Container>
-    // ---cut-after---
-)
-```
```tsx twoslash
-const Page = () => (
-    // ---cut---
-    <Container>
-        <ImportantComponent />
-    </Container>
-    // ---cut-after---
-)
-```
- +// @filename: b.ts +// ---cut--- +import { helloWorld } from './a' +console.log(helloWorld) +```

---cut-after---

The sibling to ---cut---, which trims anything after the sigil:

tsx
tsx
<Container>
<ImportantComponent />
</Container>
tsx
<Container>
<ImportantComponent />
</Container>
md
```tsx twoslash
+const Page = () => (
+    // ---cut---
+    <Container>
+        <ImportantComponent />
+    </Container>
+    // ---cut-after---
+)
+```
```tsx twoslash
+const Page = () => (
+    // ---cut---
+    <Container>
+        <ImportantComponent />
+    </Container>
+    // ---cut-after---
+)
+```
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/api/emit.html b/application/vitepress-plugin-shiki-twoslash/api/emit.html index 3b8b4acf..7fbed25b 100644 --- a/application/vitepress-plugin-shiki-twoslash/api/emit.html +++ b/application/vitepress-plugin-shiki-twoslash/api/emit.html @@ -5,15 +5,15 @@ Emit | Toshiki's Note - + - + - + - + @@ -36,46 +36,46 @@ -
Skip to content

Emit

Author:Anda Toshiki
Updated:4 minutes ago
Words:264
Reading:1 min

Running a Twoslash code example is a full TypeScript compiler run that will create files inside the virtual file system. You can replace the contents of your code examples with the results of running TypeScript over the project.

@showEmit

// @showEmit is the main command to tell Shiki Twoslash that you want to replace the output of your code example with the equivalent .js file.

ts
ts
"use strict";
const level = 'Danger';
 
ts
"use strict";
const level = 'Danger';
 
md
```ts twoslash
-// @showEmit
-const level: string = 'Danger'
-```
```ts twoslash
-// @showEmit
-const level: string = 'Danger'
-```

@showEmittedFile: [file]

While the .js file is probably the most useful file out of the box, TypeScript does emit other files if you have the right flags enabled (.d.ts and .map) but also when you have a multi-file code sample — you might need to tell Twoslash which file to show. For all these cases you can also add @showEmittedFile: [file] to tell Twoslash which file you want to show.

Shows emitted .d.ts for a TypeScript code example:

md
```ts twoslash
-// @declaration
-// @showEmit
-// @showEmittedFile: index.d.ts
-export const hello = 'world'
-```
```ts twoslash
-// @declaration
-// @showEmit
-// @showEmittedFile: index.d.ts
-export const hello = 'world'
-```
ts
ts
export declare const hello = "world";
 
ts
export declare const hello = "world";
 

Shows emitted .map files:

md
```ts twoslash
-// @sourceMap
-// @showEmit
-// @showEmittedFile: index.js.map
-export const hello = 'world'
-```
```ts twoslash
-// @sourceMap
-// @showEmit
-// @showEmittedFile: index.js.map
-export const hello = 'world'
-```
ts
ts
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
ts
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
md
```ts twoslash
-// @declaration
-// @declarationMap
-// @showEmit
-// @showEmittedFile: index.d.ts.map
-export const hello = 'world'
-```
```ts twoslash
-// @declaration
-// @declarationMap
-// @showEmit
-// @showEmittedFile: index.d.ts.map
-export const hello = 'world'
-```
ts
ts
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
ts
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
- +
Skip to content

Emit

Author:Anda Toshiki
Updated:2 minutes ago
Words:264
Reading:1 min

Running a Twoslash code example is a full TypeScript compiler run that will create files inside the virtual file system. You can replace the contents of your code examples with the results of running TypeScript over the project.

@showEmit

// @showEmit is the main command to tell Shiki Twoslash that you want to replace the output of your code example with the equivalent .js file.

ts
ts
"use strict";
const level = 'Danger';
 
ts
"use strict";
const level = 'Danger';
 
md
```ts twoslash
+// @showEmit
+const level: string = 'Danger'
+```
```ts twoslash
+// @showEmit
+const level: string = 'Danger'
+```

@showEmittedFile: [file]

While the .js file is probably the most useful file out of the box, TypeScript does emit other files if you have the right flags enabled (.d.ts and .map) but also when you have a multi-file code sample — you might need to tell Twoslash which file to show. For all these cases you can also add @showEmittedFile: [file] to tell Twoslash which file you want to show.

Shows emitted .d.ts for a TypeScript code example:

md
```ts twoslash
+// @declaration
+// @showEmit
+// @showEmittedFile: index.d.ts
+export const hello = 'world'
+```
```ts twoslash
+// @declaration
+// @showEmit
+// @showEmittedFile: index.d.ts
+export const hello = 'world'
+```
ts
ts
export declare const hello = "world";
 
ts
export declare const hello = "world";
 

Shows emitted .map files:

md
```ts twoslash
+// @sourceMap
+// @showEmit
+// @showEmittedFile: index.js.map
+export const hello = 'world'
+```
```ts twoslash
+// @sourceMap
+// @showEmit
+// @showEmittedFile: index.js.map
+export const hello = 'world'
+```
ts
ts
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
ts
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
md
```ts twoslash
+// @declaration
+// @declarationMap
+// @showEmit
+// @showEmittedFile: index.d.ts.map
+export const hello = 'world'
+```
```ts twoslash
+// @declaration
+// @declarationMap
+// @showEmit
+// @showEmittedFile: index.d.ts.map
+export const hello = 'world'
+```
ts
ts
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
ts
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/api/errors.html b/application/vitepress-plugin-shiki-twoslash/api/errors.html index 3741a16b..ed1c76f3 100644 --- a/application/vitepress-plugin-shiki-twoslash/api/errors.html +++ b/application/vitepress-plugin-shiki-twoslash/api/errors.html @@ -5,15 +5,15 @@ Errors | Toshiki's Note - + - + - + - + @@ -36,24 +36,24 @@ -
Skip to content

Errors

Author:Anda Toshiki
Updated:4 minutes ago
Words:227
Reading:1 min

Most of the time, you want to avoid errors in your code examples. Strictly speaking, this usually means setting the right compiler flags and environment in each code example.

Sometimes however, you do want to raise a compiler error — to show incorrect states. In those cases, twoslash has a way to mark the compiler errors you expect.

@errors: [num]

All TypeScript compiler errors have a number, this number is relatively arbitrary and can change between TypeScript versions. For our case these numbers are useul in declaring what we expect to see.

You can use // @errors: [num] to tell Twoslash that you expect this error to occur. This moves the compiler error message into the code example.

ts
ts
const a = '123'
= 132
Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
ts
const a = '123'
= 132
Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
md
```ts twoslash
-// @errors: 2588
-const a = '123'
-a = 132
-```
```ts twoslash
-// @errors: 2588
-const a = '123'
-a = 132
-```

@noErrors

Sometimes you have needs in which a broken TypeScript build is okay. A good example of this is using a completion query, which requires a broken TypeScript project to work. You can use // @noErrors to supress all errors in a code sample, and not have them show inline.

ts
ts
const a = '123'
a = 132
ts
const a = '123'
a = 132
md
```ts twoslash
-// @noErrors
-const a = '123'
-a = 132
-```
```ts twoslash
-// @noErrors
-const a = '123'
-a = 132
-```
- +
Skip to content

Errors

Author:Anda Toshiki
Updated:2 minutes ago
Words:227
Reading:1 min

Most of the time, you want to avoid errors in your code examples. Strictly speaking, this usually means setting the right compiler flags and environment in each code example.

Sometimes however, you do want to raise a compiler error — to show incorrect states. In those cases, twoslash has a way to mark the compiler errors you expect.

@errors: [num]

All TypeScript compiler errors have a number, this number is relatively arbitrary and can change between TypeScript versions. For our case these numbers are useul in declaring what we expect to see.

You can use // @errors: [num] to tell Twoslash that you expect this error to occur. This moves the compiler error message into the code example.

ts
ts
const a = '123'
= 132
Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
ts
const a = '123'
= 132
Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
md
```ts twoslash
+// @errors: 2588
+const a = '123'
+a = 132
+```
```ts twoslash
+// @errors: 2588
+const a = '123'
+a = 132
+```

@noErrors

Sometimes you have needs in which a broken TypeScript build is okay. A good example of this is using a completion query, which requires a broken TypeScript project to work. You can use // @noErrors to supress all errors in a code sample, and not have them show inline.

ts
ts
const a = '123'
a = 132
ts
const a = '123'
a = 132
md
```ts twoslash
+// @noErrors
+const a = '123'
+a = 132
+```
```ts twoslash
+// @noErrors
+const a = '123'
+a = 132
+```
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/api/includes.html b/application/vitepress-plugin-shiki-twoslash/api/includes.html index 645f6e50..24d0871f 100644 --- a/application/vitepress-plugin-shiki-twoslash/api/includes.html +++ b/application/vitepress-plugin-shiki-twoslash/api/includes.html @@ -5,15 +5,15 @@ Includes | Toshiki's Note - + - + - + - + @@ -36,126 +36,126 @@ -
Skip to content

Includes

Author:Anda Toshiki
Updated:4 minutes ago
Words:431
Reading:2 min

As your documentation grows, you may need a way of re-using code blocks to prevent code duplication. Shiki Twoslash provides a simple includes system.

Defining a re-usable block

Re-usable code blocks are defined by the twoslash language, followed by the include keyword and the reference name of your choice.

md
```twoslash include myBlock
-type SomeString = string
-```
```twoslash include myBlock
-type SomeString = string
-```

Incremental steps

Shiki Twoslash also provide the ability to define incremental steps through the definition of re-usable blocks. This means whenever a new step is delimited down the code, it will also include previous steps. These are not groups.

  • Incremental steps are delimited by // - [name of the step]
  • They are named at the end of the actual code
md
```twoslash include myBlockWithSteps
-type SomeString = string
-// - base
-type SomeUser = { name: string; mail?: SomeUserMail }
-type SomeUserMail = { content: string; verified: boolean }
-// - afterUserDefinitions
-type SomeGroup = { name: string; members: SomeUser[] }
-// - afterGroupDefinitions
-```
```twoslash include myBlockWithSteps
-type SomeString = string
-// - base
-type SomeUser = { name: string; mail?: SomeUserMail }
-type SomeUserMail = { content: string; verified: boolean }
-// - afterUserDefinitions
-type SomeGroup = { name: string; members: SomeUser[] }
-// - afterGroupDefinitions
-```

Including a whole block

To include a re-usable block, add // @include: [block name] in your code block.

twoslash
ts
ts
type SomeString = string
const a: SomeString = 'string'
ts
type SomeString = string
const a: SomeString = 'string'
md
```twoslash include myBlock
-type SomeString = string
-```
+    
Skip to content

Includes

Author:Anda Toshiki
Updated:2 minutes ago
Words:431
Reading:2 min

As your documentation grows, you may need a way of re-using code blocks to prevent code duplication. Shiki Twoslash provides a simple includes system.

Defining a re-usable block

Re-usable code blocks are defined by the twoslash language, followed by the include keyword and the reference name of your choice.

md
```twoslash include myBlock
+type SomeString = string
+```
```twoslash include myBlock
+type SomeString = string
+```

Incremental steps

Shiki Twoslash also provide the ability to define incremental steps through the definition of re-usable blocks. This means whenever a new step is delimited down the code, it will also include previous steps. These are not groups.

  • Incremental steps are delimited by // - [name of the step]
  • They are named at the end of the actual code
md
```twoslash include myBlockWithSteps
+type SomeString = string
+// - base
+type SomeUser = { name: string; mail?: SomeUserMail }
+type SomeUserMail = { content: string; verified: boolean }
+// - afterUserDefinitions
+type SomeGroup = { name: string; members: SomeUser[] }
+// - afterGroupDefinitions
+```
```twoslash include myBlockWithSteps
+type SomeString = string
+// - base
+type SomeUser = { name: string; mail?: SomeUserMail }
+type SomeUserMail = { content: string; verified: boolean }
+// - afterUserDefinitions
+type SomeGroup = { name: string; members: SomeUser[] }
+// - afterGroupDefinitions
+```

Including a whole block

To include a re-usable block, add // @include: [block name] in your code block.

twoslash
ts
ts
type SomeString = string
const a: SomeString = 'string'
ts
type SomeString = string
const a: SomeString = 'string'
md
```twoslash include myBlock
+type SomeString = string
+```
 
-```ts twoslash
-// @include: myBlock
-const a: SomeString = 'string'
-```
```twoslash include myBlock
-type SomeString = string
-```
+```ts twoslash
+// @include: myBlock
+const a: SomeString = 'string'
+```
```twoslash include myBlock
+type SomeString = string
+```
 
-```ts twoslash
-// @include: myBlock
-const a: SomeString = 'string'
-```

Including a block step

To include a re-usable block at a specific step, add // @include: [block name]-[step name] in your code block.

twoslash
ts
ts
type SomeString = string
type ```ts twoslash +// @include: myBlock +const a: SomeString = 'string' +```

Including a block step

To include a re-usable block at a specific step, add // @include: [block name]-[step name] in your code block.

twoslash
ts
ts
type SomeString = string
type SomeUser = { name: string; mail?: SomeUser = { name: string; mail?: SomeUserMail }
type SomeUserMail }
type SomeUserMail = { content: string; verified: boolean }
const mail: SomeUserMail = { content: string; verified: boolean }
const mail: SomeUserMail = { content: 'some-email', verified: true }
ts
type SomeString = string
type SomeUserMail = { content: 'some-email', verified: true }
ts
type SomeString = string
type SomeUser = { name: string; mail?: SomeUser = { name: string; mail?: SomeUserMail }
type SomeUserMail }
type SomeUserMail = { content: string; verified: boolean }
const mail: SomeUserMail = { content: string; verified: boolean }
const mail: SomeUserMail = { content: 'some-email', verified: true }
md
```twoslash include myBlockWithSteps
-type SomeString = string
-// - base
-type SomeUser = { name: string; mail?: SomeUserMail }
-type SomeUserMail = { content: string; verified: boolean }
-// - afterUserDefinitions
-type SomeGroup = { name: string; members: SomeUser[] }
-// - afterGroupDefinitions
-```
+}">SomeUserMail = { content: 'some-email', verified: true }
md
```twoslash include myBlockWithSteps
+type SomeString = string
+// - base
+type SomeUser = { name: string; mail?: SomeUserMail }
+type SomeUserMail = { content: string; verified: boolean }
+// - afterUserDefinitions
+type SomeGroup = { name: string; members: SomeUser[] }
+// - afterGroupDefinitions
+```
 
-```ts twoslash
-// @include: myBlockWithSteps-afterUserDefinitions
-const mail: SomeUserMail = { content: 'some-email', verified: true }
-```
```twoslash include myBlockWithSteps
-type SomeString = string
-// - base
-type SomeUser = { name: string; mail?: SomeUserMail }
-type SomeUserMail = { content: string; verified: boolean }
-// - afterUserDefinitions
-type SomeGroup = { name: string; members: SomeUser[] }
-// - afterGroupDefinitions
-```
+```ts twoslash
+// @include: myBlockWithSteps-afterUserDefinitions
+const mail: SomeUserMail = { content: 'some-email', verified: true }
+```
```twoslash include myBlockWithSteps
+type SomeString = string
+// - base
+type SomeUser = { name: string; mail?: SomeUserMail }
+type SomeUserMail = { content: string; verified: boolean }
+// - afterUserDefinitions
+type SomeGroup = { name: string; members: SomeUser[] }
+// - afterGroupDefinitions
+```
 
-```ts twoslash
-// @include: myBlockWithSteps-afterUserDefinitions
-const mail: SomeUserMail = { content: 'some-email', verified: true }
-```

Hiding re-used code

Re-using a lot of TypeScript code can easily bloat your documentation and obstruct the main point of your code block. You can hide re-used code to keep your code blocks clean and concise by cutting right after the @include statement.

ts
ts
const mail: ```ts twoslash +// @include: myBlockWithSteps-afterUserDefinitions +const mail: SomeUserMail = { content: 'some-email', verified: true } +```

Hiding re-used code

Re-using a lot of TypeScript code can easily bloat your documentation and obstruct the main point of your code block. You can hide re-used code to keep your code blocks clean and concise by cutting right after the @include statement.

ts
ts
const mail: SomeUserMail = { content: 'some-email', verified: true }
ts
const mail: SomeUserMail = { content: 'some-email', verified: true }
ts
const mail: SomeUserMail = { content: 'some-email', verified: true }
md
```twoslash include myBlockWithSteps
-type SomeString = string
-// - base
-type SomeUser = { name: string; mail?: SomeUserMail }
-type SomeUserMail = { content: string; verified: boolean }
-// - afterUserDefinitions
-type SomeGroup = { name: string; members: SomeUser[] }
-// - afterGroupDefinitions
-```
+}">SomeUserMail = { content: 'some-email', verified: true }
md
```twoslash include myBlockWithSteps
+type SomeString = string
+// - base
+type SomeUser = { name: string; mail?: SomeUserMail }
+type SomeUserMail = { content: string; verified: boolean }
+// - afterUserDefinitions
+type SomeGroup = { name: string; members: SomeUser[] }
+// - afterGroupDefinitions
+```
 
-```ts twoslash
-// @include: myBlockWithSteps-afterUserDefinitions
-// ---cut---
-const mail: SomeUserMail = { content: 'some-email', verified: true }
-```
```twoslash include myBlockWithSteps
-type SomeString = string
-// - base
-type SomeUser = { name: string; mail?: SomeUserMail }
-type SomeUserMail = { content: string; verified: boolean }
-// - afterUserDefinitions
-type SomeGroup = { name: string; members: SomeUser[] }
-// - afterGroupDefinitions
-```
+```ts twoslash
+// @include: myBlockWithSteps-afterUserDefinitions
+// ---cut---
+const mail: SomeUserMail = { content: 'some-email', verified: true }
+```
```twoslash include myBlockWithSteps
+type SomeString = string
+// - base
+type SomeUser = { name: string; mail?: SomeUserMail }
+type SomeUserMail = { content: string; verified: boolean }
+// - afterUserDefinitions
+type SomeGroup = { name: string; members: SomeUser[] }
+// - afterGroupDefinitions
+```
 
-```ts twoslash
-// @include: myBlockWithSteps-afterUserDefinitions
-// ---cut---
-const mail: SomeUserMail = { content: 'some-email', verified: true }
-```
- +```ts twoslash +// @include: myBlockWithSteps-afterUserDefinitions +// ---cut--- +const mail: SomeUserMail = { content: 'some-email', verified: true } +```
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/api/logging.html b/application/vitepress-plugin-shiki-twoslash/api/logging.html index cb0d2627..05eb88d9 100644 --- a/application/vitepress-plugin-shiki-twoslash/api/logging.html +++ b/application/vitepress-plugin-shiki-twoslash/api/logging.html @@ -5,15 +5,15 @@ Logging | Toshiki's Note - + - + - + - + @@ -36,27 +36,27 @@ -
Skip to content

Logging

Author:Anda Toshiki
Updated:4 minutes ago
Words:152
Reading:1 min

When you first see a Twoslash code example with an inline compiler error, you instinctively trust that the compiler error is correct because the design shows that it is not a part of the code sample. The logging tools lets you do that, but abuses the systemic trust because your code is not being evaluated to generate the logs.

This feature is effectively a facade, people will trust your output and it will look better.

@log:, @warn:, @error:

The names are based on the functions on the console object:

ts
ts
console.log('Hello log')
Hello log
 
console.warn('Hello warn')
Hello warn
 
console.error('Hello error')
Hello error
-
ts
console.log('Hello log')
Hello log
 
console.warn('Hello warn')
Hello warn
 
console.error('Hello error')
Hello error
md
```ts twoslash
-console.log('Hello log')
-// @log: Hello log
+    
Skip to content

Logging

Author:Anda Toshiki
Updated:2 minutes ago
Words:152
Reading:1 min

When you first see a Twoslash code example with an inline compiler error, you instinctively trust that the compiler error is correct because the design shows that it is not a part of the code sample. The logging tools lets you do that, but abuses the systemic trust because your code is not being evaluated to generate the logs.

This feature is effectively a facade, people will trust your output and it will look better.

@log:, @warn:, @error:

The names are based on the functions on the console object:

ts
ts
console.log('Hello log')
Hello log
 
console.warn('Hello warn')
Hello warn
 
console.error('Hello error')
Hello error
+
ts
console.log('Hello log')
Hello log
 
console.warn('Hello warn')
Hello warn
 
console.error('Hello error')
Hello error
md
```ts twoslash
+console.log('Hello log')
+// @log: Hello log
 
-console.warn('Hello warn')
-// @warn: Hello warn
+console.warn('Hello warn')
+// @warn: Hello warn
 
-console.error('Hello error')
-// @error: Hello error
-```
```ts twoslash
-console.log('Hello log')
-// @log: Hello log
+console.error('Hello error')
+// @error: Hello error
+```
```ts twoslash
+console.log('Hello log')
+// @log: Hello log
 
-console.warn('Hello warn')
-// @warn: Hello warn
+console.warn('Hello warn')
+// @warn: Hello warn
 
-console.error('Hello error')
-// @error: Hello error
-```
- +console.error('Hello error') +// @error: Hello error +```
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/api/multi-file.html b/application/vitepress-plugin-shiki-twoslash/api/multi-file.html index a7838495..e04fbc19 100644 --- a/application/vitepress-plugin-shiki-twoslash/api/multi-file.html +++ b/application/vitepress-plugin-shiki-twoslash/api/multi-file.html @@ -5,15 +5,15 @@ Multi-file | Toshiki's Note - + - + - + - + @@ -36,90 +36,90 @@ -
Skip to content

Multi-file

Author:Anda Toshiki
Updated:4 minutes ago
Words:477
Reading:2 min

Twoslash code examples aren't limited to creating a single file, by using // @filename: [file] you can write any file to the virtual file system used by TypeScript to power your code examples.

@filename: [file]

Most of the time, you don't need to think about the underlaying virtual file system in a code example, but when you have imports between them it becomes important to know. Twoslash will default to creating an index.[type] based on the langauge passed to the code example:

ts
ts
// I'm index.ts
ts
// I'm index.ts
md
```ts twoslash
-// I'm index.ts
-```
```ts twoslash
-// I'm index.ts
-```
tsx
tsx
// I'm index.tsx
tsx
// I'm index.tsx
md
```tsx twoslash
-// I'm index.tsx
-```
```tsx twoslash
-// I'm index.tsx
-```
js
js
// I'm index.tjs
js
// I'm index.tjs
md
```js twoslash
-// I'm index.tjs
-```
```js twoslash
-// I'm index.tjs
-```

Then until Twoslash hits another // @filename: [file], the parser keeps adding new lines into the same file. After seeing @filename Twoslash creates a new virtual file-system file and adds the new lines to that. You can't edit a file after it was created, but you can overwrite it.

It can be any file. For example, if you want to quickly fake a node module:

ts
ts
// @filename: node_modules/@types/mylib/index.d.ts
export function doit(): string
 
// @filename: index.ts
import { doit } from 'mylib'
console.log(doit)
ts
// @filename: node_modules/@types/mylib/index.d.ts
export function doit(): string
 
// @filename: index.ts
import { doit } from 'mylib'
console.log(doit)

This code example sets up the types for a non-existent npm module, and TypeScript picks it up as the definitions in the same way it would in a non-virtual TypeScript project.

md
```ts twoslash
-// @filename: node_modules/@types/mylib/index.d.ts
-export function doit(): string
+    
Skip to content

Multi-file

Author:Anda Toshiki
Updated:2 minutes ago
Words:477
Reading:2 min

Twoslash code examples aren't limited to creating a single file, by using // @filename: [file] you can write any file to the virtual file system used by TypeScript to power your code examples.

@filename: [file]

Most of the time, you don't need to think about the underlaying virtual file system in a code example, but when you have imports between them it becomes important to know. Twoslash will default to creating an index.[type] based on the langauge passed to the code example:

ts
ts
// I'm index.ts
ts
// I'm index.ts
md
```ts twoslash
+// I'm index.ts
+```
```ts twoslash
+// I'm index.ts
+```
tsx
tsx
// I'm index.tsx
tsx
// I'm index.tsx
md
```tsx twoslash
+// I'm index.tsx
+```
```tsx twoslash
+// I'm index.tsx
+```
js
js
// I'm index.tjs
js
// I'm index.tjs
md
```js twoslash
+// I'm index.tjs
+```
```js twoslash
+// I'm index.tjs
+```

Then until Twoslash hits another // @filename: [file], the parser keeps adding new lines into the same file. After seeing @filename Twoslash creates a new virtual file-system file and adds the new lines to that. You can't edit a file after it was created, but you can overwrite it.

It can be any file. For example, if you want to quickly fake a node module:

ts
ts
// @filename: node_modules/@types/mylib/index.d.ts
export function doit(): string
 
// @filename: index.ts
import { doit } from 'mylib'
console.log(doit)
ts
// @filename: node_modules/@types/mylib/index.d.ts
export function doit(): string
 
// @filename: index.ts
import { doit } from 'mylib'
console.log(doit)

This code example sets up the types for a non-existent npm module, and TypeScript picks it up as the definitions in the same way it would in a non-virtual TypeScript project.

md
```ts twoslash
+// @filename: node_modules/@types/mylib/index.d.ts
+export function doit(): string
 
-// @filename: index.ts
-import { doit } from 'mylib'
-console.log(doit)
-```
```ts twoslash
-// @filename: node_modules/@types/mylib/index.d.ts
-export function doit(): string
+// @filename: index.ts
+import { doit } from 'mylib'
+console.log(doit)
+```
```ts twoslash
+// @filename: node_modules/@types/mylib/index.d.ts
+export function doit(): string
 
-// @filename: index.ts
-import { doit } from 'mylib'
-console.log(doit)
-```

You can also set up a JSON object which can be imported in a TypeScript file:

ts
ts
// @filename: app.json
{ "version": "23.2.3" }
 
// @filename: index.ts
import appSettings from "./app.json"
appSettings.version
(property) "version": string
ts
// @filename: app.json
{ "version": "23.2.3" }
 
// @filename: index.ts
import appSettings from "./app.json"
appSettings.version
(property) "version": string
md
```ts twoslash
-// @resolveJsonModule
-// @filename: app.json
-{ "version": "23.2.3" }
+// @filename: index.ts
+import { doit } from 'mylib'
+console.log(doit)
+```

You can also set up a JSON object which can be imported in a TypeScript file:

ts
ts
// @filename: app.json
{ "version": "23.2.3" }
 
// @filename: index.ts
import appSettings from "./app.json"
appSettings.version
(property) "version": string
ts
// @filename: app.json
{ "version": "23.2.3" }
 
// @filename: index.ts
import appSettings from "./app.json"
appSettings.version
(property) "version": string
md
```ts twoslash
+// @resolveJsonModule
+// @filename: app.json
+{ "version": "23.2.3" }
 
-// @filename: index.ts
-import appSettings from "./app.json"
-appSettings.version
-//           ^?
-```
```ts twoslash
-// @resolveJsonModule
-// @filename: app.json
-{ "version": "23.2.3" }
+// @filename: index.ts
+import appSettings from "./app.json"
+appSettings.version
+//           ^?
+```
```ts twoslash
+// @resolveJsonModule
+// @filename: app.json
+{ "version": "23.2.3" }
 
-// @filename: index.ts
-import appSettings from "./app.json"
-appSettings.version
-//           ^?
-```

Finally, the following code allows importing non-TypeScript content. There is a .d.ts file which globally says 'md files are OK to import' and 'the module "react" exists, but don't worry about the details'.

Then for a user, they only see the imports and exports inside index.tsx.

ts
ts
import React from "react"
import MultiFileDocs from "./MultiFileDocs.mdx"
 
export default () => <MultiFileDocs/>
ts
import React from "react"
import MultiFileDocs from "./MultiFileDocs.mdx"
 
export default () => <MultiFileDocs/>
md
```ts twoslash
-// @filename: ambient.d.ts
-declare module '*.mdx' {
-    export default any
-}
-declare module "react"
+// @filename: index.ts
+import appSettings from "./app.json"
+appSettings.version
+//           ^?
+```

Finally, the following code allows importing non-TypeScript content. There is a .d.ts file which globally says 'md files are OK to import' and 'the module "react" exists, but don't worry about the details'.

Then for a user, they only see the imports and exports inside index.tsx.

ts
ts
import React from "react"
import MultiFileDocs from "./MultiFileDocs.mdx"
 
export default () => <MultiFileDocs/>
ts
import React from "react"
import MultiFileDocs from "./MultiFileDocs.mdx"
 
export default () => <MultiFileDocs/>
md
```ts twoslash
+// @filename: ambient.d.ts
+declare module '*.mdx' {
+    export default any
+}
+declare module "react"
 
-// @filename: MultiFileDocs.mdx
-## Hello world
+// @filename: MultiFileDocs.mdx
+## Hello world
 
-// @filename: index.tsx
-// ---cut---
-import React from "react"
-import MultiFileDocs from "./MultiFileDocs.mdx"
+// @filename: index.tsx
+// ---cut---
+import React from "react"
+import MultiFileDocs from "./MultiFileDocs.mdx"
 
-export default () => <MultiFileDocs/>
-```
```ts twoslash
-// @filename: ambient.d.ts
-declare module '*.mdx' {
-    export default any
-}
-declare module "react"
+export default () => <MultiFileDocs/>
+```
```ts twoslash
+// @filename: ambient.d.ts
+declare module '*.mdx' {
+    export default any
+}
+declare module "react"
 
-// @filename: MultiFileDocs.mdx
-## Hello world
+// @filename: MultiFileDocs.mdx
+## Hello world
 
-// @filename: index.tsx
-// ---cut---
-import React from "react"
-import MultiFileDocs from "./MultiFileDocs.mdx"
+// @filename: index.tsx
+// ---cut---
+import React from "react"
+import MultiFileDocs from "./MultiFileDocs.mdx"
 
-export default () => <MultiFileDocs/>
-```
- +export default () => <MultiFileDocs/> +```
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/api/queries.html b/application/vitepress-plugin-shiki-twoslash/api/queries.html index 7e061180..048b248b 100644 --- a/application/vitepress-plugin-shiki-twoslash/api/queries.html +++ b/application/vitepress-plugin-shiki-twoslash/api/queries.html @@ -5,15 +5,15 @@ Queries | Toshiki's Note - + - + - + - + @@ -36,24 +36,24 @@ -
Skip to content

Queries

Author:Anda Toshiki
Updated:4 minutes ago
Words:167
Reading:1 min

One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code. Twoslash comes with two different ways to query your code: ?^ and ?|.

Extract Type ^?

Using ^? you can pull out type information about a particular identifier in the line of code above it.

ts
ts
const hi = 'Hello'
const msg = hi + ', world'
const msg: string
ts
const hi = 'Hello'
const msg = hi + ', world'
const msg: string
md
```ts twoslash
-const hi = 'Hello'
-const msg = hi + ', world'
-//    ^?
-```
```ts twoslash
-const hi = 'Hello'
-const msg = hi + ', world'
-//    ^?
-```

Completions ^|

Using ^| you can pull out information about a what the auto-complete looks like at a particular location.

ts
ts
console.e
         
ts
console.e
         
md
```ts twoslash
-// @noErrors
-console.e
-//       ^|
-```
```ts twoslash
-// @noErrors
-console.e
-//       ^|
-```

INFO

Note that the compiler flag for // @noErrors is set, because console.e is a failing TypeScript code sample but we don't really care about that.

- +
Skip to content

Queries

Author:Anda Toshiki
Updated:2 minutes ago
Words:167
Reading:1 min

One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code. Twoslash comes with two different ways to query your code: ?^ and ?|.

Extract Type ^?

Using ^? you can pull out type information about a particular identifier in the line of code above it.

ts
ts
const hi = 'Hello'
const msg = hi + ', world'
const msg: string
ts
const hi = 'Hello'
const msg = hi + ', world'
const msg: string
md
```ts twoslash
+const hi = 'Hello'
+const msg = hi + ', world'
+//    ^?
+```
```ts twoslash
+const hi = 'Hello'
+const msg = hi + ', world'
+//    ^?
+```

Completions ^|

Using ^| you can pull out information about a what the auto-complete looks like at a particular location.

ts
ts
console.e
         
ts
console.e
         
md
```ts twoslash
+// @noErrors
+console.e
+//       ^|
+```
```ts twoslash
+// @noErrors
+console.e
+//       ^|
+```

INFO

Note that the compiler flag for // @noErrors is set, because console.e is a failing TypeScript code sample but we don't really care about that.

+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/api/types.html b/application/vitepress-plugin-shiki-twoslash/api/types.html index 3878d865..1ab09b74 100644 --- a/application/vitepress-plugin-shiki-twoslash/api/types.html +++ b/application/vitepress-plugin-shiki-twoslash/api/types.html @@ -5,15 +5,15 @@ @types | Toshiki's Note - + - + - + - + @@ -36,52 +36,52 @@ -
Skip to content

@types

Author:Anda Toshiki
Updated:4 minutes ago
Words:230
Reading:1 min

For most examples, you probably need to import external libraries into your code examples.

Twoslash works by faking a virtual file system over your existing file system. This means any @types or libraries with TypeScript definitions should work out of the box with no config.

Local Sources

Simply import locally installed libraries and Twoslash can pick up types:

ts
ts
import { defineConfig } from 'vitepress'
const config = defineConfig({})
const config: UserConfig<DefaultTheme.Config>
export default config
ts
import { defineConfig } from 'vitepress'
const config = defineConfig({})
const config: UserConfig<DefaultTheme.Config>
export default config
md
```ts twoslash
-import { defineConfig } from 'vitepress'
-const config = defineConfig({})
-//    ^?
-export default config
-```
```ts twoslash
-import { defineConfig } from 'vitepress'
-const config = defineConfig({})
-//    ^?
-export default config
-```

Globals

Setting up globals is a little bit more complex, but not drastically. You need to use the triple slash reference which adds a particular library to the global scope.

For example, setting up Node imports and globals etc.

ts
ts
import { writeFileSync } from 'fs'
writeFileSync('myfile.txt', '// TODO')
ts
import { writeFileSync } from 'fs'
writeFileSync('myfile.txt', '// TODO')
md
```ts twoslash
-/// <reference types="node" />
-// ---cut---
-import { writeFileSync } from 'fs'
-writeFileSync('myfile.txt', '// TODO')
-```
```ts twoslash
-/// <reference types="node" />
-// ---cut---
-import { writeFileSync } from 'fs'
-writeFileSync('myfile.txt', '// TODO')
-```

APIs like Vitest are similar cases where you would use a triple slash reference.

ts
ts
test('my tests', () => {
expect('hello').toEqual('hello')
const expect: ExpectStatic
})
ts
test('my tests', () => {
expect('hello').toEqual('hello')
const expect: ExpectStatic
})
md
```ts twoslash
-/// <reference types="vitest/globals" />
-// ---cut---
+    
Skip to content

@types

Author:Anda Toshiki
Updated:2 minutes ago
Words:230
Reading:1 min

For most examples, you probably need to import external libraries into your code examples.

Twoslash works by faking a virtual file system over your existing file system. This means any @types or libraries with TypeScript definitions should work out of the box with no config.

Local Sources

Simply import locally installed libraries and Twoslash can pick up types:

ts
ts
import { defineConfig } from 'vitepress'
const config = defineConfig({})
const config: UserConfig<DefaultTheme.Config>
export default config
ts
import { defineConfig } from 'vitepress'
const config = defineConfig({})
const config: UserConfig<DefaultTheme.Config>
export default config
md
```ts twoslash
+import { defineConfig } from 'vitepress'
+const config = defineConfig({})
+//    ^?
+export default config
+```
```ts twoslash
+import { defineConfig } from 'vitepress'
+const config = defineConfig({})
+//    ^?
+export default config
+```

Globals

Setting up globals is a little bit more complex, but not drastically. You need to use the triple slash reference which adds a particular library to the global scope.

For example, setting up Node imports and globals etc.

ts
ts
import { writeFileSync } from 'fs'
writeFileSync('myfile.txt', '// TODO')
ts
import { writeFileSync } from 'fs'
writeFileSync('myfile.txt', '// TODO')
md
```ts twoslash
+/// <reference types="node" />
+// ---cut---
+import { writeFileSync } from 'fs'
+writeFileSync('myfile.txt', '// TODO')
+```
```ts twoslash
+/// <reference types="node" />
+// ---cut---
+import { writeFileSync } from 'fs'
+writeFileSync('myfile.txt', '// TODO')
+```

APIs like Vitest are similar cases where you would use a triple slash reference.

ts
ts
test('my tests', () => {
expect('hello').toEqual('hello')
const expect: ExpectStatic
})
ts
test('my tests', () => {
expect('hello').toEqual('hello')
const expect: ExpectStatic
})
md
```ts twoslash
+/// <reference types="vitest/globals" />
+// ---cut---
 
-test('my tests', () => {
-    expect('hello').toEqual('hello')
-    // ^?
-})
-```
```ts twoslash
-/// <reference types="vitest/globals" />
-// ---cut---
+test('my tests', () => {
+    expect('hello').toEqual('hello')
+    // ^?
+})
+```
```ts twoslash
+/// <reference types="vitest/globals" />
+// ---cut---
 
-test('my tests', () => {
-    expect('hello').toEqual('hello')
-    // ^?
-})
-```
- +test('my tests', () => { + expect('hello').toEqual('hello') + // ^? +}) +```
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/config/flags.html b/application/vitepress-plugin-shiki-twoslash/config/flags.html index d87eddd6..c10209be 100644 --- a/application/vitepress-plugin-shiki-twoslash/config/flags.html +++ b/application/vitepress-plugin-shiki-twoslash/config/flags.html @@ -5,15 +5,15 @@ Compiler Flags | Toshiki's Note - + - + - + - + @@ -36,598 +36,598 @@ -
Skip to content

Compiler Flags

Author:Anda Toshiki
Updated:4 minutes ago
Words:1.1k
Reading:7 min
// @allowJs
-Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
-
-// @allowSyntheticDefaultImports
-Allow 'import x from y' when a module doesn't have a default export..
-
-// @allowUmdGlobalAccess
-Allow accessing UMD globals from modules..
-
-// @allowUnreachableCode
-Disable error reporting for unreachable code..
-
-// @allowUnusedLabels
-Disable error reporting for unused labels..
-
-// @alwaysStrict
-Ensure 'use strict' is always emitted..
-
-// @assumeChangesOnlyAffectDirectDependencies
-Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
-
-// @baseUrl
-Specify the base directory to resolve non-relative module names..
-
-// @charset
-No longer supported. In early versions, manually set the text encoding for reading files..
-
-// @checkJs
-Enable error reporting in type-checked JavaScript files..
-
-// @composite
-Enable constraints that allow a TypeScript project to be used with project references..
-
-// @declaration
-Generate .d.ts files from TypeScript and JavaScript files in your project..
-
-// @declarationDir
-Specify the output directory for generated declaration files..
-
-// @declarationMap
-Create sourcemaps for d.ts files..
-
-// @diagnostics
-Output compiler performance information after building..
-
-// @disableReferencedProjectLoad
-Reduce the number of projects loaded automatically by TypeScript..
-
-// @disableSizeLimit
-Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
-
-// @disableSolutionSearching
-Opt a project out of multi-project reference checking when editing..
-
-// @disableSourceOfProjectReferenceRedirect
-Disable preferring source files instead of declaration files when referencing composite projects.
-
-// @downlevelIteration
-Emit more compliant, but verbose and less performant JavaScript for iteration..
-
-// @emitBOM
-Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
-
-// @emitDeclarationOnly
-Only output d.ts files and not JavaScript files..
-
-// @emitDecoratorMetadata
-Emit design-type metadata for decorated declarations in source files..
-
-// @esModuleInterop
-Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
-
-// @exactOptionalPropertyTypes
-Interpret optional property types as written, rather than adding 'undefined'..
-
-// @experimentalDecorators
-Enable experimental support for TC39 stage 2 draft decorators..
-
-// @explainFiles
-Print files read during the compilation including why it was included..
-
-// @extendedDiagnostics
-Output more detailed compiler performance information after building..
-
-// @forceConsistentCasingInFileNames
-Ensure that casing is correct in imports..
-
-// @generateCpuProfile
-Emit a v8 CPU profile of the compiler run for debugging..
-
-// @importHelpers
-Allow importing helper functions from tslib once per project, instead of including them per-file..
-
-// @importsNotUsedAsValues
-Specify emit/checking behavior for imports that are only used for types.
-
-// @incremental
-Enable incremental compilation.
-
-// @inlineSourceMap
-Include sourcemap files inside the emitted JavaScript..
-
-// @inlineSources
-Include source code in the sourcemaps inside the emitted JavaScript..
-
-// @isolatedModules
-Ensure that each file can be safely transpiled without relying on other imports..
-
-// @jsx
-Specify what JSX code is generated..
-
-// @jsxFactory
-Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
-
-// @jsxFragmentFactory
-Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
-
-// @jsxImportSource
-Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
-
-// @keyofStringsOnly
-Make keyof only return strings instead of string, numbers or symbols. Legacy option..
-
-// @lib
-Specify a set of bundled library declaration files that describe the target runtime environment..
-
-// @listEmittedFiles
-Print the names of emitted files after a compilation..
-
-// @listFiles
-Print all of the files read during the compilation..
-
-// @mapRoot
-Specify the location where debugger should locate map files instead of generated locations..
-
-// @maxNodeModuleJsDepth
-Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
-
-// @module
-Specify what module code is generated..
-
-// @moduleResolution
-Specify how TypeScript looks up a file from a given module specifier..
-
-// @newLine
-Set the newline character for emitting files..
-
-// @noEmit
-Disable emitting file from a compilation..
-
-// @noEmitHelpers
-Disable generating custom helper functions like `__extends` in compiled output..
-
-// @noEmitOnError
-Disable emitting files if any type checking errors are reported..
-
-// @noErrorTruncation
-Disable truncating types in error messages..
-
-// @noFallthroughCasesInSwitch
-Enable error reporting for fallthrough cases in switch statements..
-
-// @noImplicitAny
-Enable error reporting for expressions and declarations with an implied `any` type...
-
-// @noImplicitOverride
-Add `undefined` to a type when accessed using an index..
-
-// @noImplicitReturns
-Enable error reporting for codepaths that do not explicitly return in a function..
-
-// @noImplicitThis
-Enable error reporting when `this` is given the type `any`..
-
-// @noImplicitUseStrict
-Disable adding 'use strict' directives in emitted JavaScript files..
-
-// @noLib
-Disable including any library files, including the default lib.d.ts..
-
-// @noPropertyAccessFromIndexSignature
-Enforces using indexed accessors for keys declared using an indexed type.
-
-// @noResolve
-Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
-
-// @noStrictGenericChecks
-Disable strict checking of generic signatures in function types..
-
-// @noUncheckedIndexedAccess
-Include 'undefined' in index signature results.
-
-// @noUnusedLocals
-Enable error reporting when a local variables aren't read..
-
-// @noUnusedParameters
-Raise an error when a function parameter isn't read.
-
-// @out
-Deprecated setting. Use `outFile` instead..
-
-// @outDir
-Specify an output folder for all emitted files..
-
-// @outFile
-Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
-
-// @paths
-Specify a set of entries that re-map imports to additional lookup locations..
-
-// @plugins
-List of language service plugins..
-
-// @preserveConstEnums
-Disable erasing `const enum` declarations in generated code..
-
-// @preserveSymlinks
-Disable resolving symlinks to their realpath. This correlates to the same flag in node..
-
-// @preserveWatchOutput
-Disable wiping the console in watch mode.
-
-// @pretty
-Enable color and formatting in output to make compiler errors easier to read.
-
-// @reactNamespace
-Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
-
-// @removeComments
-Disable emitting comments..
-
-// @resolveJsonModule
-Enable importing .json files.
-
-// @rootDir
-Specify the root folder within your source files..
-
-// @rootDirs
-Allow multiple folders to be treated as one when resolving modules..
-
-// @skipDefaultLibCheck
-Skip type checking .d.ts files that are included with TypeScript..
-
-// @skipLibCheck
-Skip type checking all .d.ts files..
-
-// @sourceMap
-Create source map files for emitted JavaScript files..
-
-// @sourceRoot
-Specify the root path for debuggers to find the reference source code..
-
-// @strict
-Enable all strict type-checking options..
-
-// @strictBindCallApply
-Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
-
-// @strictFunctionTypes
-When assigning functions, check to ensure parameters and the return values are subtype-compatible..
-
-// @strictNullChecks
-When type checking, take into account `null` and `undefined`..
-
-// @strictPropertyInitialization
-Check for class properties that are declared but not set in the constructor..
-
-// @stripInternal
-Disable emitting declarations that have `@internal` in their JSDoc comments..
-
-// @suppressExcessPropertyErrors
-Disable reporting of excess property errors during the creation of object literals..
-
-// @suppressImplicitAnyIndexErrors
-Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
-
-// @target
-Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
-
-// @traceResolution
-Log paths used during the `moduleResolution` process..
-
-// @tsBuildInfoFile
-Specify the folder for .tsbuildinfo incremental compilation files..
-
-// @typeRoots
-Specify multiple folders that act like `./node_modules/@types`..
-
-// @types
-Specify type package names to be included without being referenced in a source file..
-
-// @useDefineForClassFields
-Emit ECMAScript-standard-compliant class fields..
-
-// @useUnknownInCatchVariables
-Type catch clause variables as 'unknown' instead of 'any'..
// @allowJs
-Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
-
-// @allowSyntheticDefaultImports
-Allow 'import x from y' when a module doesn't have a default export..
-
-// @allowUmdGlobalAccess
-Allow accessing UMD globals from modules..
-
-// @allowUnreachableCode
-Disable error reporting for unreachable code..
-
-// @allowUnusedLabels
-Disable error reporting for unused labels..
-
-// @alwaysStrict
-Ensure 'use strict' is always emitted..
-
-// @assumeChangesOnlyAffectDirectDependencies
-Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
-
-// @baseUrl
-Specify the base directory to resolve non-relative module names..
-
-// @charset
-No longer supported. In early versions, manually set the text encoding for reading files..
-
-// @checkJs
-Enable error reporting in type-checked JavaScript files..
-
-// @composite
-Enable constraints that allow a TypeScript project to be used with project references..
-
-// @declaration
-Generate .d.ts files from TypeScript and JavaScript files in your project..
-
-// @declarationDir
-Specify the output directory for generated declaration files..
-
-// @declarationMap
-Create sourcemaps for d.ts files..
-
-// @diagnostics
-Output compiler performance information after building..
-
-// @disableReferencedProjectLoad
-Reduce the number of projects loaded automatically by TypeScript..
-
-// @disableSizeLimit
-Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
-
-// @disableSolutionSearching
-Opt a project out of multi-project reference checking when editing..
-
-// @disableSourceOfProjectReferenceRedirect
-Disable preferring source files instead of declaration files when referencing composite projects.
-
-// @downlevelIteration
-Emit more compliant, but verbose and less performant JavaScript for iteration..
-
-// @emitBOM
-Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
-
-// @emitDeclarationOnly
-Only output d.ts files and not JavaScript files..
-
-// @emitDecoratorMetadata
-Emit design-type metadata for decorated declarations in source files..
-
-// @esModuleInterop
-Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
-
-// @exactOptionalPropertyTypes
-Interpret optional property types as written, rather than adding 'undefined'..
-
-// @experimentalDecorators
-Enable experimental support for TC39 stage 2 draft decorators..
-
-// @explainFiles
-Print files read during the compilation including why it was included..
-
-// @extendedDiagnostics
-Output more detailed compiler performance information after building..
-
-// @forceConsistentCasingInFileNames
-Ensure that casing is correct in imports..
-
-// @generateCpuProfile
-Emit a v8 CPU profile of the compiler run for debugging..
-
-// @importHelpers
-Allow importing helper functions from tslib once per project, instead of including them per-file..
-
-// @importsNotUsedAsValues
-Specify emit/checking behavior for imports that are only used for types.
-
-// @incremental
-Enable incremental compilation.
-
-// @inlineSourceMap
-Include sourcemap files inside the emitted JavaScript..
-
-// @inlineSources
-Include source code in the sourcemaps inside the emitted JavaScript..
-
-// @isolatedModules
-Ensure that each file can be safely transpiled without relying on other imports..
-
-// @jsx
-Specify what JSX code is generated..
-
-// @jsxFactory
-Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
-
-// @jsxFragmentFactory
-Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
-
-// @jsxImportSource
-Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
-
-// @keyofStringsOnly
-Make keyof only return strings instead of string, numbers or symbols. Legacy option..
-
-// @lib
-Specify a set of bundled library declaration files that describe the target runtime environment..
-
-// @listEmittedFiles
-Print the names of emitted files after a compilation..
-
-// @listFiles
-Print all of the files read during the compilation..
-
-// @mapRoot
-Specify the location where debugger should locate map files instead of generated locations..
-
-// @maxNodeModuleJsDepth
-Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
-
-// @module
-Specify what module code is generated..
-
-// @moduleResolution
-Specify how TypeScript looks up a file from a given module specifier..
-
-// @newLine
-Set the newline character for emitting files..
-
-// @noEmit
-Disable emitting file from a compilation..
-
-// @noEmitHelpers
-Disable generating custom helper functions like `__extends` in compiled output..
-
-// @noEmitOnError
-Disable emitting files if any type checking errors are reported..
-
-// @noErrorTruncation
-Disable truncating types in error messages..
-
-// @noFallthroughCasesInSwitch
-Enable error reporting for fallthrough cases in switch statements..
-
-// @noImplicitAny
-Enable error reporting for expressions and declarations with an implied `any` type...
-
-// @noImplicitOverride
-Add `undefined` to a type when accessed using an index..
-
-// @noImplicitReturns
-Enable error reporting for codepaths that do not explicitly return in a function..
-
-// @noImplicitThis
-Enable error reporting when `this` is given the type `any`..
-
-// @noImplicitUseStrict
-Disable adding 'use strict' directives in emitted JavaScript files..
-
-// @noLib
-Disable including any library files, including the default lib.d.ts..
-
-// @noPropertyAccessFromIndexSignature
-Enforces using indexed accessors for keys declared using an indexed type.
-
-// @noResolve
-Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
-
-// @noStrictGenericChecks
-Disable strict checking of generic signatures in function types..
-
-// @noUncheckedIndexedAccess
-Include 'undefined' in index signature results.
-
-// @noUnusedLocals
-Enable error reporting when a local variables aren't read..
-
-// @noUnusedParameters
-Raise an error when a function parameter isn't read.
-
-// @out
-Deprecated setting. Use `outFile` instead..
-
-// @outDir
-Specify an output folder for all emitted files..
-
-// @outFile
-Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
-
-// @paths
-Specify a set of entries that re-map imports to additional lookup locations..
-
-// @plugins
-List of language service plugins..
-
-// @preserveConstEnums
-Disable erasing `const enum` declarations in generated code..
-
-// @preserveSymlinks
-Disable resolving symlinks to their realpath. This correlates to the same flag in node..
-
-// @preserveWatchOutput
-Disable wiping the console in watch mode.
-
-// @pretty
-Enable color and formatting in output to make compiler errors easier to read.
-
-// @reactNamespace
-Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
-
-// @removeComments
-Disable emitting comments..
-
-// @resolveJsonModule
-Enable importing .json files.
-
-// @rootDir
-Specify the root folder within your source files..
-
-// @rootDirs
-Allow multiple folders to be treated as one when resolving modules..
-
-// @skipDefaultLibCheck
-Skip type checking .d.ts files that are included with TypeScript..
-
-// @skipLibCheck
-Skip type checking all .d.ts files..
-
-// @sourceMap
-Create source map files for emitted JavaScript files..
-
-// @sourceRoot
-Specify the root path for debuggers to find the reference source code..
-
-// @strict
-Enable all strict type-checking options..
-
-// @strictBindCallApply
-Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
-
-// @strictFunctionTypes
-When assigning functions, check to ensure parameters and the return values are subtype-compatible..
-
-// @strictNullChecks
-When type checking, take into account `null` and `undefined`..
-
-// @strictPropertyInitialization
-Check for class properties that are declared but not set in the constructor..
-
-// @stripInternal
-Disable emitting declarations that have `@internal` in their JSDoc comments..
-
-// @suppressExcessPropertyErrors
-Disable reporting of excess property errors during the creation of object literals..
-
-// @suppressImplicitAnyIndexErrors
-Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
-
-// @target
-Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
-
-// @traceResolution
-Log paths used during the `moduleResolution` process..
-
-// @tsBuildInfoFile
-Specify the folder for .tsbuildinfo incremental compilation files..
-
-// @typeRoots
-Specify multiple folders that act like `./node_modules/@types`..
-
-// @types
-Specify type package names to be included without being referenced in a source file..
-
-// @useDefineForClassFields
-Emit ECMAScript-standard-compliant class fields..
-
-// @useUnknownInCatchVariables
-Type catch clause variables as 'unknown' instead of 'any'..
- +
Skip to content

Compiler Flags

Author:Anda Toshiki
Updated:2 minutes ago
Words:1.1k
Reading:7 min
// @allowJs
+Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
+
+// @allowSyntheticDefaultImports
+Allow 'import x from y' when a module doesn't have a default export..
+
+// @allowUmdGlobalAccess
+Allow accessing UMD globals from modules..
+
+// @allowUnreachableCode
+Disable error reporting for unreachable code..
+
+// @allowUnusedLabels
+Disable error reporting for unused labels..
+
+// @alwaysStrict
+Ensure 'use strict' is always emitted..
+
+// @assumeChangesOnlyAffectDirectDependencies
+Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
+
+// @baseUrl
+Specify the base directory to resolve non-relative module names..
+
+// @charset
+No longer supported. In early versions, manually set the text encoding for reading files..
+
+// @checkJs
+Enable error reporting in type-checked JavaScript files..
+
+// @composite
+Enable constraints that allow a TypeScript project to be used with project references..
+
+// @declaration
+Generate .d.ts files from TypeScript and JavaScript files in your project..
+
+// @declarationDir
+Specify the output directory for generated declaration files..
+
+// @declarationMap
+Create sourcemaps for d.ts files..
+
+// @diagnostics
+Output compiler performance information after building..
+
+// @disableReferencedProjectLoad
+Reduce the number of projects loaded automatically by TypeScript..
+
+// @disableSizeLimit
+Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
+
+// @disableSolutionSearching
+Opt a project out of multi-project reference checking when editing..
+
+// @disableSourceOfProjectReferenceRedirect
+Disable preferring source files instead of declaration files when referencing composite projects.
+
+// @downlevelIteration
+Emit more compliant, but verbose and less performant JavaScript for iteration..
+
+// @emitBOM
+Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
+
+// @emitDeclarationOnly
+Only output d.ts files and not JavaScript files..
+
+// @emitDecoratorMetadata
+Emit design-type metadata for decorated declarations in source files..
+
+// @esModuleInterop
+Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
+
+// @exactOptionalPropertyTypes
+Interpret optional property types as written, rather than adding 'undefined'..
+
+// @experimentalDecorators
+Enable experimental support for TC39 stage 2 draft decorators..
+
+// @explainFiles
+Print files read during the compilation including why it was included..
+
+// @extendedDiagnostics
+Output more detailed compiler performance information after building..
+
+// @forceConsistentCasingInFileNames
+Ensure that casing is correct in imports..
+
+// @generateCpuProfile
+Emit a v8 CPU profile of the compiler run for debugging..
+
+// @importHelpers
+Allow importing helper functions from tslib once per project, instead of including them per-file..
+
+// @importsNotUsedAsValues
+Specify emit/checking behavior for imports that are only used for types.
+
+// @incremental
+Enable incremental compilation.
+
+// @inlineSourceMap
+Include sourcemap files inside the emitted JavaScript..
+
+// @inlineSources
+Include source code in the sourcemaps inside the emitted JavaScript..
+
+// @isolatedModules
+Ensure that each file can be safely transpiled without relying on other imports..
+
+// @jsx
+Specify what JSX code is generated..
+
+// @jsxFactory
+Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
+
+// @jsxFragmentFactory
+Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
+
+// @jsxImportSource
+Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
+
+// @keyofStringsOnly
+Make keyof only return strings instead of string, numbers or symbols. Legacy option..
+
+// @lib
+Specify a set of bundled library declaration files that describe the target runtime environment..
+
+// @listEmittedFiles
+Print the names of emitted files after a compilation..
+
+// @listFiles
+Print all of the files read during the compilation..
+
+// @mapRoot
+Specify the location where debugger should locate map files instead of generated locations..
+
+// @maxNodeModuleJsDepth
+Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
+
+// @module
+Specify what module code is generated..
+
+// @moduleResolution
+Specify how TypeScript looks up a file from a given module specifier..
+
+// @newLine
+Set the newline character for emitting files..
+
+// @noEmit
+Disable emitting file from a compilation..
+
+// @noEmitHelpers
+Disable generating custom helper functions like `__extends` in compiled output..
+
+// @noEmitOnError
+Disable emitting files if any type checking errors are reported..
+
+// @noErrorTruncation
+Disable truncating types in error messages..
+
+// @noFallthroughCasesInSwitch
+Enable error reporting for fallthrough cases in switch statements..
+
+// @noImplicitAny
+Enable error reporting for expressions and declarations with an implied `any` type...
+
+// @noImplicitOverride
+Add `undefined` to a type when accessed using an index..
+
+// @noImplicitReturns
+Enable error reporting for codepaths that do not explicitly return in a function..
+
+// @noImplicitThis
+Enable error reporting when `this` is given the type `any`..
+
+// @noImplicitUseStrict
+Disable adding 'use strict' directives in emitted JavaScript files..
+
+// @noLib
+Disable including any library files, including the default lib.d.ts..
+
+// @noPropertyAccessFromIndexSignature
+Enforces using indexed accessors for keys declared using an indexed type.
+
+// @noResolve
+Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
+
+// @noStrictGenericChecks
+Disable strict checking of generic signatures in function types..
+
+// @noUncheckedIndexedAccess
+Include 'undefined' in index signature results.
+
+// @noUnusedLocals
+Enable error reporting when a local variables aren't read..
+
+// @noUnusedParameters
+Raise an error when a function parameter isn't read.
+
+// @out
+Deprecated setting. Use `outFile` instead..
+
+// @outDir
+Specify an output folder for all emitted files..
+
+// @outFile
+Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
+
+// @paths
+Specify a set of entries that re-map imports to additional lookup locations..
+
+// @plugins
+List of language service plugins..
+
+// @preserveConstEnums
+Disable erasing `const enum` declarations in generated code..
+
+// @preserveSymlinks
+Disable resolving symlinks to their realpath. This correlates to the same flag in node..
+
+// @preserveWatchOutput
+Disable wiping the console in watch mode.
+
+// @pretty
+Enable color and formatting in output to make compiler errors easier to read.
+
+// @reactNamespace
+Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
+
+// @removeComments
+Disable emitting comments..
+
+// @resolveJsonModule
+Enable importing .json files.
+
+// @rootDir
+Specify the root folder within your source files..
+
+// @rootDirs
+Allow multiple folders to be treated as one when resolving modules..
+
+// @skipDefaultLibCheck
+Skip type checking .d.ts files that are included with TypeScript..
+
+// @skipLibCheck
+Skip type checking all .d.ts files..
+
+// @sourceMap
+Create source map files for emitted JavaScript files..
+
+// @sourceRoot
+Specify the root path for debuggers to find the reference source code..
+
+// @strict
+Enable all strict type-checking options..
+
+// @strictBindCallApply
+Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
+
+// @strictFunctionTypes
+When assigning functions, check to ensure parameters and the return values are subtype-compatible..
+
+// @strictNullChecks
+When type checking, take into account `null` and `undefined`..
+
+// @strictPropertyInitialization
+Check for class properties that are declared but not set in the constructor..
+
+// @stripInternal
+Disable emitting declarations that have `@internal` in their JSDoc comments..
+
+// @suppressExcessPropertyErrors
+Disable reporting of excess property errors during the creation of object literals..
+
+// @suppressImplicitAnyIndexErrors
+Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
+
+// @target
+Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
+
+// @traceResolution
+Log paths used during the `moduleResolution` process..
+
+// @tsBuildInfoFile
+Specify the folder for .tsbuildinfo incremental compilation files..
+
+// @typeRoots
+Specify multiple folders that act like `./node_modules/@types`..
+
+// @types
+Specify type package names to be included without being referenced in a source file..
+
+// @useDefineForClassFields
+Emit ECMAScript-standard-compliant class fields..
+
+// @useUnknownInCatchVariables
+Type catch clause variables as 'unknown' instead of 'any'..
// @allowJs
+Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
+
+// @allowSyntheticDefaultImports
+Allow 'import x from y' when a module doesn't have a default export..
+
+// @allowUmdGlobalAccess
+Allow accessing UMD globals from modules..
+
+// @allowUnreachableCode
+Disable error reporting for unreachable code..
+
+// @allowUnusedLabels
+Disable error reporting for unused labels..
+
+// @alwaysStrict
+Ensure 'use strict' is always emitted..
+
+// @assumeChangesOnlyAffectDirectDependencies
+Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
+
+// @baseUrl
+Specify the base directory to resolve non-relative module names..
+
+// @charset
+No longer supported. In early versions, manually set the text encoding for reading files..
+
+// @checkJs
+Enable error reporting in type-checked JavaScript files..
+
+// @composite
+Enable constraints that allow a TypeScript project to be used with project references..
+
+// @declaration
+Generate .d.ts files from TypeScript and JavaScript files in your project..
+
+// @declarationDir
+Specify the output directory for generated declaration files..
+
+// @declarationMap
+Create sourcemaps for d.ts files..
+
+// @diagnostics
+Output compiler performance information after building..
+
+// @disableReferencedProjectLoad
+Reduce the number of projects loaded automatically by TypeScript..
+
+// @disableSizeLimit
+Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
+
+// @disableSolutionSearching
+Opt a project out of multi-project reference checking when editing..
+
+// @disableSourceOfProjectReferenceRedirect
+Disable preferring source files instead of declaration files when referencing composite projects.
+
+// @downlevelIteration
+Emit more compliant, but verbose and less performant JavaScript for iteration..
+
+// @emitBOM
+Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
+
+// @emitDeclarationOnly
+Only output d.ts files and not JavaScript files..
+
+// @emitDecoratorMetadata
+Emit design-type metadata for decorated declarations in source files..
+
+// @esModuleInterop
+Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
+
+// @exactOptionalPropertyTypes
+Interpret optional property types as written, rather than adding 'undefined'..
+
+// @experimentalDecorators
+Enable experimental support for TC39 stage 2 draft decorators..
+
+// @explainFiles
+Print files read during the compilation including why it was included..
+
+// @extendedDiagnostics
+Output more detailed compiler performance information after building..
+
+// @forceConsistentCasingInFileNames
+Ensure that casing is correct in imports..
+
+// @generateCpuProfile
+Emit a v8 CPU profile of the compiler run for debugging..
+
+// @importHelpers
+Allow importing helper functions from tslib once per project, instead of including them per-file..
+
+// @importsNotUsedAsValues
+Specify emit/checking behavior for imports that are only used for types.
+
+// @incremental
+Enable incremental compilation.
+
+// @inlineSourceMap
+Include sourcemap files inside the emitted JavaScript..
+
+// @inlineSources
+Include source code in the sourcemaps inside the emitted JavaScript..
+
+// @isolatedModules
+Ensure that each file can be safely transpiled without relying on other imports..
+
+// @jsx
+Specify what JSX code is generated..
+
+// @jsxFactory
+Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
+
+// @jsxFragmentFactory
+Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
+
+// @jsxImportSource
+Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
+
+// @keyofStringsOnly
+Make keyof only return strings instead of string, numbers or symbols. Legacy option..
+
+// @lib
+Specify a set of bundled library declaration files that describe the target runtime environment..
+
+// @listEmittedFiles
+Print the names of emitted files after a compilation..
+
+// @listFiles
+Print all of the files read during the compilation..
+
+// @mapRoot
+Specify the location where debugger should locate map files instead of generated locations..
+
+// @maxNodeModuleJsDepth
+Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
+
+// @module
+Specify what module code is generated..
+
+// @moduleResolution
+Specify how TypeScript looks up a file from a given module specifier..
+
+// @newLine
+Set the newline character for emitting files..
+
+// @noEmit
+Disable emitting file from a compilation..
+
+// @noEmitHelpers
+Disable generating custom helper functions like `__extends` in compiled output..
+
+// @noEmitOnError
+Disable emitting files if any type checking errors are reported..
+
+// @noErrorTruncation
+Disable truncating types in error messages..
+
+// @noFallthroughCasesInSwitch
+Enable error reporting for fallthrough cases in switch statements..
+
+// @noImplicitAny
+Enable error reporting for expressions and declarations with an implied `any` type...
+
+// @noImplicitOverride
+Add `undefined` to a type when accessed using an index..
+
+// @noImplicitReturns
+Enable error reporting for codepaths that do not explicitly return in a function..
+
+// @noImplicitThis
+Enable error reporting when `this` is given the type `any`..
+
+// @noImplicitUseStrict
+Disable adding 'use strict' directives in emitted JavaScript files..
+
+// @noLib
+Disable including any library files, including the default lib.d.ts..
+
+// @noPropertyAccessFromIndexSignature
+Enforces using indexed accessors for keys declared using an indexed type.
+
+// @noResolve
+Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
+
+// @noStrictGenericChecks
+Disable strict checking of generic signatures in function types..
+
+// @noUncheckedIndexedAccess
+Include 'undefined' in index signature results.
+
+// @noUnusedLocals
+Enable error reporting when a local variables aren't read..
+
+// @noUnusedParameters
+Raise an error when a function parameter isn't read.
+
+// @out
+Deprecated setting. Use `outFile` instead..
+
+// @outDir
+Specify an output folder for all emitted files..
+
+// @outFile
+Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
+
+// @paths
+Specify a set of entries that re-map imports to additional lookup locations..
+
+// @plugins
+List of language service plugins..
+
+// @preserveConstEnums
+Disable erasing `const enum` declarations in generated code..
+
+// @preserveSymlinks
+Disable resolving symlinks to their realpath. This correlates to the same flag in node..
+
+// @preserveWatchOutput
+Disable wiping the console in watch mode.
+
+// @pretty
+Enable color and formatting in output to make compiler errors easier to read.
+
+// @reactNamespace
+Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
+
+// @removeComments
+Disable emitting comments..
+
+// @resolveJsonModule
+Enable importing .json files.
+
+// @rootDir
+Specify the root folder within your source files..
+
+// @rootDirs
+Allow multiple folders to be treated as one when resolving modules..
+
+// @skipDefaultLibCheck
+Skip type checking .d.ts files that are included with TypeScript..
+
+// @skipLibCheck
+Skip type checking all .d.ts files..
+
+// @sourceMap
+Create source map files for emitted JavaScript files..
+
+// @sourceRoot
+Specify the root path for debuggers to find the reference source code..
+
+// @strict
+Enable all strict type-checking options..
+
+// @strictBindCallApply
+Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
+
+// @strictFunctionTypes
+When assigning functions, check to ensure parameters and the return values are subtype-compatible..
+
+// @strictNullChecks
+When type checking, take into account `null` and `undefined`..
+
+// @strictPropertyInitialization
+Check for class properties that are declared but not set in the constructor..
+
+// @stripInternal
+Disable emitting declarations that have `@internal` in their JSDoc comments..
+
+// @suppressExcessPropertyErrors
+Disable reporting of excess property errors during the creation of object literals..
+
+// @suppressImplicitAnyIndexErrors
+Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
+
+// @target
+Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
+
+// @traceResolution
+Log paths used during the `moduleResolution` process..
+
+// @tsBuildInfoFile
+Specify the folder for .tsbuildinfo incremental compilation files..
+
+// @typeRoots
+Specify multiple folders that act like `./node_modules/@types`..
+
+// @types
+Specify type package names to be included without being referenced in a source file..
+
+// @useDefineForClassFields
+Emit ECMAScript-standard-compliant class fields..
+
+// @useUnknownInCatchVariables
+Type catch clause variables as 'unknown' instead of 'any'..
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/config/reference.html b/application/vitepress-plugin-shiki-twoslash/config/reference.html index 8e1f63a6..d214aa55 100644 --- a/application/vitepress-plugin-shiki-twoslash/config/reference.html +++ b/application/vitepress-plugin-shiki-twoslash/config/reference.html @@ -5,15 +5,15 @@ Config | Toshiki's Note - + - + - + - + @@ -36,90 +36,90 @@ -
Skip to content

Config

Author:Anda Toshiki
Updated:4 minutes ago
Words:248
Reading:1 min

Overview

You can configure VitePress Twoslash using the twoslash property added to defineConfig.

ts
ts
// .vitepress/config.[ext]
import { defineConfig } from 'vitepress'
import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
 
export default withTwoslash(
defineConfig({
twoslash: {
// Your VitePress Twoslash options
},
})
)
ts
// .vitepress/config.[ext]
import { defineConfig } from 'vitepress'
import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
 
export default withTwoslash(
defineConfig({
twoslash: {
// Your VitePress Twoslash options
},
})
)

INFO

In addition to the below config options, VitePress Twoslash also supports all shiki HighlighterOptions and @typescript/twoslash TwoSlashOptions.

Options

addTryButton

A way to turn on the try buttons seen on the TS website.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            addTryButton: true, 
-        },
-    })
-)
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            addTryButton: true, 
-        },
-    })
-)

alwayRaiseForTwoslashExceptions

Instead of showing twoslash exceptions inline, throw the entire process like it will on CI.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            alwayRaiseForTwoslashExceptions: true, 
-        },
-    })
-)
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            alwayRaiseForTwoslashExceptions: true, 
-        },
-    })
-)

disableImplicitReactImport

A way to disable implicit React imports on tsx/jsx language codeblocks

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            disableImplicitReactImport: true, 
-        },
-    })
-)
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            disableImplicitReactImport: true, 
-        },
-    })
-)

includeJSDocInHover

Include JSDoc comments in the hovers.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            includeJSDocInHover: true, 
-        },
-    })
-)
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            includeJSDocInHover: true, 
-        },
-    })
-)

ignoreCodeblocksWithCodefenceMeta

Ignore transforming certain code blocks.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            ignoreCodeblocksWithCodefenceMeta: true, 
-        },
-    })
-)
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            ignoreCodeblocksWithCodefenceMeta: true, 
-        },
-    })
-)

wrapFragments

A way to add a div wrapper for multi-theme outputs.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            wrapFragments: true, 
-        },
-    })
-)
export default withTwoslash(
-    defineConfig({
-        twoslash: {
-            wrapFragments: true, 
-        },
-    })
-)
- +
Skip to content

Config

Author:Anda Toshiki
Updated:2 minutes ago
Words:248
Reading:1 min

Overview

You can configure VitePress Twoslash using the twoslash property added to defineConfig.

ts
ts
// .vitepress/config.[ext]
import { defineConfig } from 'vitepress'
import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
 
export default withTwoslash(
defineConfig({
twoslash: {
// Your VitePress Twoslash options
},
})
)
ts
// .vitepress/config.[ext]
import { defineConfig } from 'vitepress'
import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
 
export default withTwoslash(
defineConfig({
twoslash: {
// Your VitePress Twoslash options
},
})
)

INFO

In addition to the below config options, VitePress Twoslash also supports all shiki HighlighterOptions and @typescript/twoslash TwoSlashOptions.

Options

addTryButton

A way to turn on the try buttons seen on the TS website.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            addTryButton: true, 
+        },
+    })
+)
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            addTryButton: true, 
+        },
+    })
+)

alwayRaiseForTwoslashExceptions

Instead of showing twoslash exceptions inline, throw the entire process like it will on CI.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            alwayRaiseForTwoslashExceptions: true, 
+        },
+    })
+)
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            alwayRaiseForTwoslashExceptions: true, 
+        },
+    })
+)

disableImplicitReactImport

A way to disable implicit React imports on tsx/jsx language codeblocks

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            disableImplicitReactImport: true, 
+        },
+    })
+)
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            disableImplicitReactImport: true, 
+        },
+    })
+)

includeJSDocInHover

Include JSDoc comments in the hovers.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            includeJSDocInHover: true, 
+        },
+    })
+)
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            includeJSDocInHover: true, 
+        },
+    })
+)

ignoreCodeblocksWithCodefenceMeta

Ignore transforming certain code blocks.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            ignoreCodeblocksWithCodefenceMeta: true, 
+        },
+    })
+)
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            ignoreCodeblocksWithCodefenceMeta: true, 
+        },
+    })
+)

wrapFragments

A way to add a div wrapper for multi-theme outputs.

  • Type: boolean
  • Default: false
ts
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            wrapFragments: true, 
+        },
+    })
+)
export default withTwoslash(
+    defineConfig({
+        twoslash: {
+            wrapFragments: true, 
+        },
+    })
+)
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/guide/custom-theme.html b/application/vitepress-plugin-shiki-twoslash/guide/custom-theme.html index 7e1d87ef..de2fb38c 100644 --- a/application/vitepress-plugin-shiki-twoslash/guide/custom-theme.html +++ b/application/vitepress-plugin-shiki-twoslash/guide/custom-theme.html @@ -5,15 +5,15 @@ Using a Custom Theme | Toshiki's Note - + - + - + - + @@ -36,92 +36,92 @@ -
Skip to content

Using a Custom Theme

Author:Anda Toshiki
Updated:4 minutes ago
Words:362
Reading:2 min

Twoslash uses your markdown.theme for syntax highlighting, but there are a few other things you can do to customize the look and feel of your code examples — particulary the generated Twoslash interface.

CSS Variables

The following CSS variables (and their defaults) are available to style Twoslash interface:

css
:root {
-    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
+    
Skip to content

Using a Custom Theme

Author:Anda Toshiki
Updated:2 minutes ago
Words:362
Reading:2 min

Twoslash uses your markdown.theme for syntax highlighting, but there are a few other things you can do to customize the look and feel of your code examples — particulary the generated Twoslash interface.

CSS Variables

The following CSS variables (and their defaults) are available to style Twoslash interface:

css
:root {
+    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
 
-    --vp-twoslash-c-brand: var(--vp-c-brand);
+    --vp-twoslash-c-brand: var(--vp-c-brand);
 
-    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
-    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
+    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
+    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
 
-    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
-    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
-    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
-    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
-    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
-    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
-    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
+    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
+    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
+    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
+    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
+    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
+    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
+    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
 
-    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
-    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
-    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
-    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
-    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
+    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
+    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
+    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
+    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
+    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
 
-    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
-    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
-    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
-}
:root {
-    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
+    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
+    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
+    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
+}
:root {
+    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
 
-    --vp-twoslash-c-brand: var(--vp-c-brand);
+    --vp-twoslash-c-brand: var(--vp-c-brand);
 
-    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
-    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
+    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
+    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
 
-    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
-    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
-    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
-    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
-    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
-    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
-    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
+    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
+    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
+    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
+    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
+    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
+    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
+    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
 
-    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
-    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
-    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
-    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
-    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
+    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
+    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
+    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
+    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
+    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
 
-    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
-    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
-    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
-}

Dark/Light Theme

If you pass a responsive theme to markdown.theme, you probably also want to hide/show the correct theme based on the user's settings.

ts
ts
export default defineConfig({
markdown: {
theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
},
})
ts
export default defineConfig({
markdown: {
theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
},
})

You can do this with the following CSS:

css
/*
- * Hide block based on theme
- * `[class*='-dark']` matches `'vitesse-dark'`
- * `[class*='-light']` matches `'vitesse-light'`
- */
-html:not(.dark) pre.shiki[class*='-dark'] {
-    display: none;
-}
-html:not(.dark) pre.shiki[class*='-light'] {
-    display: block;
-}
-html.dark pre.shiki[class*='-dark'] {
-    display: block;
-}
-html.dark pre.shiki[class*='-light'] {
-    display: none;
-}
/*
- * Hide block based on theme
- * `[class*='-dark']` matches `'vitesse-dark'`
- * `[class*='-light']` matches `'vitesse-light'`
- */
-html:not(.dark) pre.shiki[class*='-dark'] {
-    display: none;
-}
-html:not(.dark) pre.shiki[class*='-light'] {
-    display: block;
-}
-html.dark pre.shiki[class*='-dark'] {
-    display: block;
-}
-html.dark pre.shiki[class*='-light'] {
-    display: none;
-}
- + --vp-twoslash-c-query-bg: var(--vp-c-mute-darker); + --vp-twoslash-c-query-fg-2: var(--vp-c-text-2); + --vp-twoslash-c-query-fg: var(--vp-c-text-1); +}

Dark/Light Theme

If you pass a responsive theme to markdown.theme, you probably also want to hide/show the correct theme based on the user's settings.

ts
ts
export default defineConfig({
markdown: {
theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
},
})
ts
export default defineConfig({
markdown: {
theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
},
})

You can do this with the following CSS:

css
/*
+ * Hide block based on theme
+ * `[class*='-dark']` matches `'vitesse-dark'`
+ * `[class*='-light']` matches `'vitesse-light'`
+ */
+html:not(.dark) pre.shiki[class*='-dark'] {
+    display: none;
+}
+html:not(.dark) pre.shiki[class*='-light'] {
+    display: block;
+}
+html.dark pre.shiki[class*='-dark'] {
+    display: block;
+}
+html.dark pre.shiki[class*='-light'] {
+    display: none;
+}
/*
+ * Hide block based on theme
+ * `[class*='-dark']` matches `'vitesse-dark'`
+ * `[class*='-light']` matches `'vitesse-light'`
+ */
+html:not(.dark) pre.shiki[class*='-dark'] {
+    display: none;
+}
+html:not(.dark) pre.shiki[class*='-light'] {
+    display: block;
+}
+html.dark pre.shiki[class*='-dark'] {
+    display: block;
+}
+html.dark pre.shiki[class*='-light'] {
+    display: none;
+}
+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.html b/application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.html index 2afad01c..fdded3ca 100644 --- a/application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.html +++ b/application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.html @@ -5,15 +5,15 @@ Markdown Extensions | Toshiki's Note - + - + - + - + @@ -36,14 +36,14 @@ -
Skip to content

Markdown Extensions

Author:Anda Toshiki
Updated:4 minutes ago
Words:181
Reading:1 min

Code Groups

Code Groups and Twoslash multi-file support.

ts
ts
import { name } from './name'
export function hello(name: string) {
console.log(`Hello, ${name}!`)
}
hello(name)
(alias) const name: "twoslash" -import name
ts
import { name } from './name'
export function hello(name: string) {
console.log(`Hello, ${name}!`)
}
hello(name)
(alias) const name: "twoslash" -import name
ts
ts
export const name = 'twoslash'
ts
export const name = 'twoslash'

Unsupported Extensions

Since VitePress Twoslash uses it's own Shiki highlighter, the following syntax highlighting extensions are not currently compatible.

If you are interested in adding support, please start a new GitHub Discussion.

- +
Skip to content

Markdown Extensions

Author:Anda Toshiki
Updated:2 minutes ago
Words:181
Reading:1 min

Code Groups

Code Groups and Twoslash multi-file support.

ts
ts
import { name } from './name'
export function hello(name: string) {
console.log(`Hello, ${name}!`)
}
hello(name)
(alias) const name: "twoslash" +import name
ts
import { name } from './name'
export function hello(name: string) {
console.log(`Hello, ${name}!`)
}
hello(name)
(alias) const name: "twoslash" +import name
ts
ts
export const name = 'twoslash'
ts
export const name = 'twoslash'

Unsupported Extensions

Since VitePress Twoslash uses it's own Shiki highlighter, the following syntax highlighting extensions are not currently compatible.

If you are interested in adding support, please start a new GitHub Discussion.

+ \ No newline at end of file diff --git a/application/vitepress-plugin-shiki-twoslash/index.html b/application/vitepress-plugin-shiki-twoslash/index.html index 1f450d52..269a1d5a 100644 --- a/application/vitepress-plugin-shiki-twoslash/index.html +++ b/application/vitepress-plugin-shiki-twoslash/index.html @@ -5,15 +5,15 @@ VitePress Twoslash: VitePress Plugin for Shiki Twoslash - + - + - + - + @@ -36,118 +36,118 @@ -
Skip to content

@andatoshiki/vitepress-plugin-shiki-twoslash

Author:Anda Toshiki
Updated:4 minutes ago
Words:437
Reading:2 min

Static code examples for VitePress using Shiki Twoslash — powered by the syntax engine of Visual Studio Code and the TypeScript compiler.

Overview

Try moving your cursor into the code block below:

ts
ts
// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property]
}
 
type
Skip to content

@andatoshiki/vitepress-plugin-shiki-twoslash

Author:Anda Toshiki
Updated:2 minutes ago
Words:437
Reading:2 min

Static code examples for VitePress using Shiki Twoslash — powered by the syntax engine of Visual Studio Code and the TypeScript compiler.

Overview

Try moving your cursor into the code block below:

ts
ts
// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property]
}
 
type LockedAccount = {
readonly id: string
readonly name: string
}
 
type LockedAccount = {
readonly id: string
readonly name: string
}
 
type UnlockedAccount = CreateMutable<UnlockedAccount = CreateMutable<LockedAccount>
ts
// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property]
}
 
type LockedAccount>
ts
// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property]
}
 
type LockedAccount = {
readonly id: string
readonly name: string
}
 
type LockedAccount = {
readonly id: string
readonly name: string
}
 
type UnlockedAccount = CreateMutable<UnlockedAccount = CreateMutable<LockedAccount>

Pretty neat, right? To some extent, anything your editor can show you about code, Twoslash can show. For example, here is the real auto-complete for a VitePress config:

ts
ts
import { defineConfig } from 'vitepress'
 
export default defineConfig({
ti,
      
})
ts
import { defineConfig } from 'vitepress'
 
export default defineConfig({
ti,
      
})

The name Twoslash refers to specially formatted comments (e.g. // ^?) which can be used to set up your environment, like compiler flags or separate input files. It couldn't be easier to set up and start creating incredible code examples!

Install

Install @andatoshiki/vitepress-plugin-shiki-twoslash (requires vitepress@>=1.0.0-alpha.61).

bash
pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
bash
npm i @andatoshiki/vitepress-plugin-shiki-twoslash
npm i @andatoshiki/vitepress-plugin-shiki-twoslash
bash
yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
yarn add @andatoshiki/vitepress-plugin-shiki-twoslash

WARNING

Until shiki-twoslash uses the same version of shiki as VitePress, you must override the following packages' shiki versions for syntax highlighting to look the same.

json
{
-    "pnpm": {
-        "overrides": {
-            "remark-shiki-twoslash>shiki": "^0.14.1",
-            "shiki-twoslash>shiki": "^0.14.1"
-        }
-    }
-}
{
-    "pnpm": {
-        "overrides": {
-            "remark-shiki-twoslash>shiki": "^0.14.1",
-            "shiki-twoslash>shiki": "^0.14.1"
-        }
-    }
-}

Tracked in an upstream issue: https://github.com/shikijs/twoslash/issues/180

Configure

First, wrap your VitePress config file with the withTwoslash wrapper.

ts
ts
// .vitepress/config.[ext]
import { defineConfig } from 'vitepress'
import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
 
export default withTwoslash(
defineConfig({
// Your VitePress config
})
)
ts
// .vitepress/config.[ext]
import { defineConfig } from 'vitepress'
import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
 
export default withTwoslash(
defineConfig({
// Your VitePress config
})
)

Then, import @andatoshiki/vitepress-plugin-shiki-twoslash/styles.css into your theme.

ts
ts
// .vitepress/theme/index.ts
import LockedAccount>

Pretty neat, right? To some extent, anything your editor can show you about code, Twoslash can show. For example, here is the real auto-complete for a VitePress config:

ts
ts
import { defineConfig } from 'vitepress'
 
export default defineConfig({
ti,
      
})
ts
import { defineConfig } from 'vitepress'
 
export default defineConfig({
ti,
      
})

The name Twoslash refers to specially formatted comments (e.g. // ^?) which can be used to set up your environment, like compiler flags or separate input files. It couldn't be easier to set up and start creating incredible code examples!

Install

Install @andatoshiki/vitepress-plugin-shiki-twoslash (requires vitepress@>=1.0.0-alpha.61).

bash
pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
bash
npm i @andatoshiki/vitepress-plugin-shiki-twoslash
npm i @andatoshiki/vitepress-plugin-shiki-twoslash
bash
yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
yarn add @andatoshiki/vitepress-plugin-shiki-twoslash

WARNING

Until shiki-twoslash uses the same version of shiki as VitePress, you must override the following packages' shiki versions for syntax highlighting to look the same.

json
{
+    "pnpm": {
+        "overrides": {
+            "remark-shiki-twoslash>shiki": "^0.14.1",
+            "shiki-twoslash>shiki": "^0.14.1"
+        }
+    }
+}
{
+    "pnpm": {
+        "overrides": {
+            "remark-shiki-twoslash>shiki": "^0.14.1",
+            "shiki-twoslash>shiki": "^0.14.1"
+        }
+    }
+}

Tracked in an upstream issue: https://github.com/shikijs/twoslash/issues/180

Configure

First, wrap your VitePress config file with the withTwoslash wrapper.

ts
ts
// .vitepress/config.[ext]
import { defineConfig } from 'vitepress'
import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
 
export default withTwoslash(
defineConfig({
// Your VitePress config
})
)
ts
// .vitepress/config.[ext]
import { defineConfig } from 'vitepress'
import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
 
export default withTwoslash(
defineConfig({
// Your VitePress config
})
)

Then, import @andatoshiki/vitepress-plugin-shiki-twoslash/styles.css into your theme.

ts
ts
// .vitepress/theme/index.ts
import defaultTheme from 'vitepress/theme'
import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
 
export default defaultTheme from 'vitepress/theme'
import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
 
export default defaultTheme
ts
// .vitepress/theme/index.ts
import defaultTheme
ts
// .vitepress/theme/index.ts
import defaultTheme from 'vitepress/theme'
import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
 
export default defaultTheme from 'vitepress/theme'
import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
 
export default defaultTheme

TIP

You can configure VitePress Twoslash using the twoslash property added to defineConfig.

Add Twoslash

Finally, add the twoslash attribute to markdown fenced code blocks.

md
```ts twoslash
-// Removes 'readonly' attributes from a type's properties
-type CreateMutable<Type> = {
-    -readonly [Property in keyof Type]: Type[Property]
-}
+import defaultTheme">defaultTheme

TIP

You can configure VitePress Twoslash using the twoslash property added to defineConfig.

Add Twoslash

Finally, add the twoslash attribute to markdown fenced code blocks.

md
```ts twoslash
+// Removes 'readonly' attributes from a type's properties
+type CreateMutable<Type> = {
+    -readonly [Property in keyof Type]: Type[Property]
+}
 
-type LockedAccount = {
-    readonly id: string
-    readonly name: string
-}
+type LockedAccount = {
+    readonly id: string
+    readonly name: string
+}
 
-type UnlockedAccount = CreateMutable<LockedAccount>
-//   ^?
-```
```ts twoslash
-// Removes 'readonly' attributes from a type's properties
-type CreateMutable<Type> = {
-    -readonly [Property in keyof Type]: Type[Property]
-}
+type UnlockedAccount = CreateMutable<LockedAccount>
+//   ^?
+```
```ts twoslash
+// Removes 'readonly' attributes from a type's properties
+type CreateMutable<Type> = {
+    -readonly [Property in keyof Type]: Type[Property]
+}
 
-type LockedAccount = {
-    readonly id: string
-    readonly name: string
-}
+type LockedAccount = {
+    readonly id: string
+    readonly name: string
+}
 
-type UnlockedAccount = CreateMutable<LockedAccount>
-//   ^?
-```

And your code blocks will be twoslashified!

ts
ts
// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property]
}
 
type type UnlockedAccount = CreateMutable<LockedAccount> +// ^? +```

And your code blocks will be twoslashified!

ts
ts
// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property]
}
 
type LockedAccount = {
readonly id: string
readonly name: string
}
 
type LockedAccount = {
readonly id: string
readonly name: string
}
 
type UnlockedAccount = CreateMutable<UnlockedAccount = CreateMutable<LockedAccount>
type UnlockedAccount = { +}">LockedAccount
>
type UnlockedAccount = { id: string; name: string; -}
ts
// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property]
}
 
type
ts
// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property]
}
 
type LockedAccount = {
readonly id: string
readonly name: string
}
 
type LockedAccount = {
readonly id: string
readonly name: string
}
 
type UnlockedAccount = CreateMutable<UnlockedAccount = CreateMutable<LockedAccount>
type UnlockedAccount = { +}">LockedAccount
>
type UnlockedAccount = { id: string; name: string; -}
- +}
+ \ No newline at end of file diff --git a/assets/2023-11-02-04-44-14.08b67c2b.png b/assets/2023-11-02-04-44-14.08b67c2b.png new file mode 100644 index 0000000000000000000000000000000000000000..ae08dddef9657f3d4dfb5b92d2771bb68d9bd4a7 GIT binary patch literal 346782 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 z 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 puAA% literal 0 HcmV?d00001 diff --git a/assets/2023-11-04-00-42-58.d7bf77fb.png b/assets/2023-11-04-00-42-58.d7bf77fb.png new file mode 100644 index 0000000000000000000000000000000000000000..8899cb0d5e08dc68a46909eb73eb3fbd6f23d01b GIT binary patch literal 505971 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

XYOSzPQi3pKP=I$7ytLvisxdLnRZ+ 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 J)hr$$SnQFH>h(OF&hMy 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

  • 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%0Ass; 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 X$zSfYM}PbPe)jJ@uqX4sr*HlbaDfKU literal 0 HcmV?d00001 diff --git a/assets/2023-11-04-01-32-28.da2149a9.png b/assets/2023-11-04-01-32-28.da2149a9.png new file mode 100644 index 0000000000000000000000000000000000000000..c4a3e7e04c1233c6a16ed137dd487ccfa8d3b08f GIT binary patch literal 365642 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

    =)1Q2>bx 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

    AO(5@vP$i|K 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 R`waZsw#998_Rohd{10z&5y$`l literal 0 HcmV?d00001 diff --git a/assets/2023-11-04-03-15-12.77ab4cd9.png b/assets/2023-11-04-03-15-12.77ab4cd9.png new file mode 100644 index 0000000000000000000000000000000000000000..91a8391ae6ea59e208e8a0c16c11e936bec469d3 GIT binary patch literal 167926 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%0Alv6BR+8cl#Tso3X@ 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≷c=UXB1$3MCYK`W)ontV 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 FV1m7)4xs=5 literal 0 HcmV?d00001 diff --git a/assets/2023-11-04-03-49-38.78c93d29.png b/assets/2023-11-04-03-49-38.78c93d29.png new file mode 100644 index 0000000000000000000000000000000000000000..6847f099f8cd1780dd97ada71cc6a4624d709873 GIT binary patch literal 179688 zcmXtgb9`Li7wyD08aB3@G>x4!X5+@TZQG5L#%Ro$cw*bOZR6$p-uwM=Klj|3`_G(n z_Fil4z0O1^%Kt<`BtQfJ04P$DV#)vjo zwg&(R0i?u)f4M`PX2baF^vw-S)ccfQp+7)lGD3^k(=@e;(w(D*{oU*`d{9lR5pL>fir{{NavRWoB5g;wCt4+5Nj8*58?8_# z4JG~}?-E9W?%5(yiCEM?3PpS*-fDTW7A*Ot)EywyIepX+B0|PMOItHMEX@!Z{EvlL zvN$ooy;I`4O^Sn5B(p4r1fns_hJK~LfuP(6CpOI8F^B0Ah)#) z*fBaa+P?mNybNm|K3pbr&r~Um^WH81JC6^mW^-FzZ~B6E&lXRDS4y?$vO*E4?!}x& zw(r8C*z zrpfQ**YuDWUdi^Xhp|P8bZ#+K2hrl>Ft||zt7|PVx>Ts`S&)^?o13)E_;6P_LQfIL z`K%B-Gq^-!-|M+a4%$M5#lp#X7^u70Akzn0Id|V3Wc|4!J!>L4T6Aq11)=C_K#x0? zEE=)=IS?ACluxO$@WrNl3B^ugmLex5mQ4K-MH0}(c=zBz;p)LgiJd)pHL5gN=RExCg?hP&w{K6oeL7Tn+$`mq;imG+Y4BR13T<5eQ+2YEC(Jmw9AF3TCb0Lk3(o znQxg&MpZ7_LbIL9v2YeyOB}Uvu>HC_@GXQ+{@+cX*IJ$UVgC#Y$vniTwu1O8L- za~W6$+1V9H#MbJzdupDbEHD4qK&>CvXk>@`RX~QW5|7mUw!ocWXVZSdO3F3JUECjC zFnD@NU;=N#x#uOlHr@iYBv|H-A`~jD{S^6SU~qV0Z{x^F-^Pg4%~o?|;y&lVD0j+; zG!;R5a$9HbGO`&DjWZaz_H{&K%Ux|Zl*xdrNLBorHjl&=hL z0A^1BHED?l{37eP4?aD-Pb|3WrIe|7+XCI~ILcFJc(vK{{TaFQxT`=Cl; zun*!WiZ{;68VfcHtICQn6@JLux>8p$S*4fNZV!TU_d= zr3YAXJhcm5S%c(Ay{!HGO#YcAO~~*Tp8tt zp7vC_rEMS5EwBmnG<+oLO>`jSH_ejEdy{A>6^7l_C=_S>I2&w$h|c0l=;B43*rBq#x>$)@$x zjpf&FA%LMLryNhvw4NLmSx_jqlzL$k`f*(DY4}GdKab{yu1|%`fV}G>S(w(!JX2*u zQ*TD{AB_f8E16W58bI$CG=XsMQRQ0t)6-e_fXYw=_!A3s5AJ92ChEM(G)U6E4x(r1 z03jxg0eXA2hW*0YOjoF>Q4guJ$qF$C;g{jvlH zZLoc`5qIz*Q{j|{3TMdQqkHs}-ld)rx0{)3S`#iL)t-Ko-OOsuWUsGQ4$oAb8JXam-))@GW0)(zYL`m{xucskq~o9g?V*3-wACE1sOrW>`WO z)i;nEudrxN8iG#y*))jK;0ex+UZ71fRLT#_JlD#(tDFL1$3K%DvgIpS4h!l|FrqjD z2D~7L3)KiMROiJs>)tBrf!_8I*m2gobVjSKk}-sVMhI3_rJDRDI?}{Ee1VJpsG`8L zB=t!6aBia(iOq3e6TEs!mDF&TPUrOi$q_ zg(LVg>@?2e1QH0SQkXo+sn#=iJ2}bGn|pD>2c)w@FY)wk^lmy%Uxx{`lA20tLD?V~ zKnAA$tSAiWqc69aeRSaTo`rug9z0-$p*V|T0ZRm+*NUe}XaTK__M&jx<0T6PJY?}!_b`03zLPfDV6H7#ANLZ5+w^Ie$ zEs!4TK*EOPv)UC~*Gu1*-1Q4n7|9w#B;^}i4NR6t%2-c~CfK@jP0|$S2v^xM7w$vh zO*MvDn#nr^&$pX965WsI=L7Y-_aat+wCrZ>?{74cp6X&y_(;S_iXj)G(f30v`S5}f z_H?oF-(viG+}8ajPzAR@DZ6jhZ1%Y^g#7)(2C#;6nkY!;iA@Xw<4>*VH$Nj6c`t#_ zpP2|h>(MWh5!M?vcc|mJc-$WMX{%XCAww>i`8Y%WF-x<7)(P;%ku2 zCN5M(g$I&M@&rhl=phlEIOIyogr)nU?bZQ0T3B1pF=GJQBcz7RL$BuhCf!!%AW|l+ygi{^fQ5N6B)$onOO0 zr+rN_)UX>9(;*1mOl}{c&UKRq{9(Z+opBWWOMCzt);lo5uru={!~EgR_Jbr)h@n~k_K{2o(r3YMpOq0{q`^)#rPY1 z5*%3y^77#omd$xS45#b1yVt``+-arT1`uYC?WT^2w(y(8A?1qHmDsja#-+kn?$rf= zvHkIfO$**7zJKw{d8Xrp_T*DN?N39GbieZyPc8Um_EpA4dfr5Bv2=SPmroXjXxK3bTQ0*zdh4TCiIqYiai%^4w}|+ zqpy)G(r!gLU8IPs@ws2^0WKMMiOD6djQ%x=K*T)Xd@4zMFpi$&g;&r)$jMAa$4PbO|;dFIjl6gE~rdc62 zke^<2Xxiugr||wfhS&pqLtR-W^E$H{IQPpH*RBU_1bP6?_hrB6o!4DBWQVssVEZzo zlAFdt=$Eq~4E_3h$_&(#a+)oC#!_*>-)2egy?;Pxr&nm4W`>J*6V&q0u#;kJU2PT@ zzRv{tkb4pH4CH>$j1XrI+~j`vwN)*4}5d#qNLMF_Zj8wZwZDau@|9w{26+ z-sy@t5S#cG)>CZX_Qb^%DNUty&XiD8(`0IHy?jgov)~FWJ(MdqpZOfd-Llua*kIA* z(<4}Xz=f{O$qxHN)`M?vnvz+dFnX^ny5-#T@WD9nK+j{$w*A8(lhq|uTQu+Y6cLAi z6N;tO(9ccb^;{09C}GzICf8NLO`}{k10jkvI1;EBIH>jTN(HXjAR)`2v;$6~8)xFe zVtn5)o=t-|*Jf>7-XDNH_q-ZJB^?}53$)aN`E5_Z8Fce}<7MtzcxF!kOj7ziCHiHY zk}_w6ky}oN`q@Coa#Fs^2Ee}=ogFs%J4?L{JOCPr?hhvpz%uG7tT5vCmXK+agZzree*0h9oOgk}g?gHhq#@20y81 zVAT`K#!EqUuFdYD=VQkx*TG2NL!h~TO%!~0@&&dH6z7dqRUR_WCS6Wa0%7e@g zG(ub6KqYF6Blf){D~0G*i;2+-7NlRPb-qoUbRZJ7b~`{h@_8ba39o}z5TgjaC!MV- z(s5kso3EBp=RK&nVdPJR@m($YB)O!zeSkv~5AiPuC7Nw5J3RYc(%%3r?Zwhh$YO{U z8Izqtn&~*sN2b++H__P+>)dJ)JNgd-?WZdk6l+-ZcA77am~G+T!~{Q)wnji-AEAEw zdGb3L?Su-JZ+r6;Oh@#r{Lx!`iUd6d#nJQS8|aJhirca$(#zwR`so$;qX$*+P+w+T zPd~ZBiKL60u}mo^aFb$>d*GYN0hWQL?KaD(sX+FhbJ4SjL_W2}%GS4&^n=rl39xOl zqX+|4a%B+pZTb~?;&5g(b)QWL3FY}O=?>J>1-PvH>E9QR+y@>~t6*GK@(B@QiOyC9 zOh4PJ*dGmZE|A;?%HKZlhzxl&ddP;|5tzyv%5waGZ-aN2S28RsGI9Ktq8lD7=S`0y zR$Z0X$l+Y3Q$T|Ur(vDdwe(6f0ayZl*j~4n&y9CwK&t-&2i5hnd&~ZXgWh{EbYu|( z75wpMC$_!-m47s_)T`WdtRB)CoY715Si9^Uy0~zwAx0-dYZ=S*ArC1+LXM=vC_+on zXjeC;7F-l&vszA5UgY>4RvsqaXJNTy9dA^R3)3YwkWBW+d{!L* zj4pyS5KCzH8C;F+qVf>6EHG(N+pLTYvRkBRid99kp`n*O|3wl46ocT+_hQ{=n=x%< za{wn7d@A3SjN1q1?YnC4@Vyq0Gp5At0cCmVY(dASn*XLD+j({hmz2dDlF*wyu@~EL zL%nPrpj=AnDwRox5J(@}#6gj`QZSs+n{3Rb!msT@;cn~c6JU&W-gvmp$P2U zt1$OzmUT~A%c1heiSnB;@~h9hcuIodX=tRU6^wW}#=I3#Q$3xZIzMP>M-`Z)p2)I< z*n4#g5;1oB9(as=U8O3LZX>J&J)q#5Uld-C?cjKAj48lW(;JOHUvFmTwMC+^Y~;3T z7Ir4WDH-kuT@^4gBxjvk#~WFhFRP{UA7eaZ-4v*oSg-_l$st17t``qjqZPjnLVL4@ zaJ@xG-v59jHn-z@snBumg2AP&ZWumdXZlSHstF#n42RDEl$;-!T7>9?g>bqa`-Xc2f8g9a%G?SMS&YT(6O+II&s$UM;MEfsvAK_*TUW^- zH((-Psd2;3nxfBtP{^m0EV;P=lK>s4I3me)+d3?EdW}i+lqfrn*>%6>@}>3adZcoq zI5YmxBtTVNZI*F($MBKLhc{ATOgG!*Zh{r|PHRg?{o*pwH}WxT8CZ+f@zjqh_>4#R z-1T$5-G_JfBRFL!Y84;kGw3w=|TXL=sX5J-<>17o__7 zZ9Z~x5gO9oOmem^uCTy;7i1N7qa$dwo*(1$<5au+s~{|4`#7)ii2=infR!K9hwi!8 zT+?T=oxaTJcN5+fKzH2=ns1xkAJ4Rjdp&VzJsKC}T?322Cb43WJ!eD@=oR(v&?3=k zmI`*Z?Yz$qbhZo#jgK~*6YhX=EsS#Wx-`%u{|0Tl6AfuHs|yG$-Mu&;8~ZgsOx!>21ei-I#3T5WCUB3huPNy!{CbG5}69PbFrt{nr0G%R*F6sSYl^ssydu z8kNX58tD0*B(j?{z?9<$eZ5j|Y<@xE552+)7KS(6mP)YX5-=+Mevqx}JLYn~bW**P z$C_(EuO!v)poLtF=AWn3AT$tKb`$qmTl|5{!Evy!P55?S5r!B4yFqM;mYvOQCvm}W z=ooHth;yN?Mtm`qh3CYY@Olf*_10mapwXlcq*qddZH*Dt9lt4lGRT6(vFkMQ%}(PO zCS**SNx%%ZeA37COV$-3k2t;7EE)n{&|*H3u>HTr3NTGl{lQ|<7rkvFz`*-!REY7$ z&%X2DM}?L&U-e|3mh%x;Tsr|jsK0vdRu@`X2e1H?u$vQK%5tTQEH$CQdCzyRj1>62 zVTG3Gd{J@uW|`Kr6MucTrM&j@z>B!;UfNQBYT?*Ly>|$_ z(j^*5X`2Tis26`Ip3L7*9f(>7nfBecjxg7YnKTzoD$^3%Q&w<@$vt3UomFTw405hH zG8|Z49TvoG6AeZBw6Pb-x+1;hZlmQID%6ZRKA;j;U|FQ=c^?U;{1qIS?%g$$rL{V% z=JiLmZ4qywH{&9&VB4(wSM}u zDz9@OR-C}F=~(YpwKzMy(3_svJpaGHP9yXMKUR1Y0&kD|ffrdHq_+zj&PjJCYa_!v zKoF&Yi4LwSpG^ib+ZK*_zu%fKlL|NC@C1_DmzPtpm)qUma^4>M%z$hAgxX?lC?TUgKOGL#|MbuaJmL-VA~&&RyH#Ej&N{Qk zXa7#u7rzyx&;`42FO)4iPqy?yw6IDdxeYUp>JN`&yU~!B16G#Sm z5q#l-@D0Lv41llp{e_np)Xge@TyLha_gFh$X~N+3(f6^auhd@5xoD*kT`UMzQ2SMLF9PB4 zh_CRW;Zh{JoCo(+p9J}3yi6mHt(V?676RQaReN3wsCf65gZ`l&>n z9rjq-Dcs{8>gMFDa(X1PWb(TL=5aLfU6d+Ih8?d>bBK=bQ3$8kzH{r_e&*@i$J+$z znwy}^Sh`gNLQ*9>B)N7itfLT6^PkxQB;{>ZV5!gJyVty3fdFo(V&5=BR&T2<{G8U| ztu$YLWU#Eb7CzhG27b4-HG$VlQJHP9(iksN0;81hUkK%!Vm3Hv`~331-6ZkDuX#0aK(%=+32wr;;iGQ+*Pl-J^`lJUl4YI>OOP2o(e@JOYBd=?pKNH zRw&=xba@;M0@v$=uqBWvxUK+oeL|l1oVIndVnYjQdvL>ZkIL)(AC1k49A`ZuUk#RQ zUDt40h&YEmz}Z?pUcWAn1B`=})FLY_j=Z=>ATXGPiswF(hQ5*9i@b|THHckJf-I@#({Yj+xr;UPNC-bq?6yifACu{%`9S-zI_{Gu-~x zSEpFiwB$oi(?tpIfnSbjG6Vk6thRm6h$5FMjFR+{4J_a=W#9_(mnGaSl#Ir=Aapx2 zF91Jv%X43&TdC!Sgf>2(r|3AVt~gkM@)FALY%kNF}Un#@q0H}2T>>;02?jFn@^*>a?k ziQ)cdr=-JL>htdiD06Y5+K9yzqZ!wqwbNSFtvm2o3e;~RcY?4!0`tT5j3hZ@8mk}b zExR1=L`A#Mi?*3IXYFnqA?&o|c96j&za$e=_=v`@qjd;^Xdp;$ zNM)_kA*0fH+-KICUx_nh!p>6A62&!|?1bNLtq3{X^$71qSa7YUmZ$S*ts(Z2xoKO* z&5<`>08j)2!Be4L@6Urht~;vg8s&zVU%N)IyI>|WPw30&cS&hUAV|ECE3p2X2_9iD zEYDJE=VWBz(~UfD=_>RKa$JWhof7V73;naId&CvX@w!iqs!z~XC&E9+7AN{ZNN%8DJucUGmZ z-8Mcn6QgO@wt8>cc(M70M7YTyfa!N#O^X9v_YRb0N0pVmPAHq*@GZ5~;^Z;qL2}vH zYeM6G9*fv;T*X8Ey^3@-{uJ?$ae;+(k0+{=xn?LMDvNKv0P=T3$f_x{|K`C4*}VVy zGqf`LgiP}V;=AtIi%Q`AoD#u&&I|naes1dq2iZ=*Y`=AJ*Qcj1i*6gfR&eKj{;INB zz0$r;(MJm+b5ab(jr<_rk&M5$si6qr8d{pC97{X3?`voqE1i|;JqT}6Mlm-*B;geOvlnK&RSh+@hqas zHJ;G-=hwE0z8oo#WdyK}8tlzl06oAlXE&gYMq=Rlu*-^zFfnIqgkwJM;m2p)9+&O2 zd1HmKBzLSt?u#z-1|?tesy+kC%G1L6QSYYfGqT*c*7n7-_(SkA)8P!TBe(Wrz>iS(CiH_%D{bL4vGc`tB=+3K18>fY0O7fm+1D z!@3tL@UiVlvcBT|K%C6IcVor#$B)KJb3!rJvWKuEv5_O(gwqn_i1(vZ-5OFQ2vu}1 zxZey(@ug;YA|Hc=?x>n1JJC508{SA^U6AD!A`ZH6x3=@7?nbi9aBMWUWL?`r9KE{a zt9BT1g4<~YOpA3PPHMgx|M_*_%Gvmw*ZMNhsvN}%bGMXc zuuEGa+7-?rO(n3<-{;}&!S(X}rDt(Vfy_)EkKw1W3%>hoIU2~;ghC>wrsS{RxV*pv zkqj0mo~tRKoiNf%g5Uf29S5Si{q90(?YnAy0jDMM<^e`^1<*8`R~zJNbGA_-qA5+D zdj^LFbew&|ICh$%T_sT@9=|6W3r)f3kIrqRz+(tvBXiz-2d(>T7@DJ8Mk(0_V@;8I z%d7Oek2z#OUxb10*lIG^NE3!XD*y~J5E!mwNg0VJ0l24LA=|$)dB7*AyxJw7nqTI_ zV;t6|qv-9W_Gje>=ZeN&lLKQDIf4xSt(aK7m<|r_S`D?4?;$7>?mW*b0%G&2VX}<$ z*VH`ISpXbKgYXJ+UAEimP$E*pV_f3;B{y3$5+#Bq3#j>A%qOs3fF0m0(Dxz}MQe&s z`ugrwYkVC>;$y7C>jFeIhaTJ-?e{$FuvRIZ30hsK@}gIUv%GDs0*9eNiI2jSnBEYluM0jF$#M=391GY z-sJ09P+UNAx6t|K(3)E^%&DLC0|IM$SbT=|pFc}~5O%D)7ZY6HaKQC6dVWhPWX0rFSKs}sh=Pq+q^@2+tZQ<@8Pwb|Pw?{M9FJ~YScCb*{Nxbz8 z`Md7Qf~M%rT^FlmscV^rD$8^kjZbj(V7!PV&2U*G+*5t`RsvsvXAvY_FNw2+tZh^FN2w|mfM zix?jE6$2(8 zjbx@FOeK|T z@>x3Q+A7W}z+;i`nF;@e!BDJ(aX4B!So*Tzeb#-I1y!8Ix+j+(&1Z$UiuWt%7l2>7 z*~h>zFadDv8Jhp?OC9ZGCQEx&jR5a4$V{V2eg&2 z8;L2x)|23ed8-{Lx&3b2DHcpBGRe<|N!wILipQ^mkl5f{cR(m)f?9~D@*fo}(-$h3 z`HZo07^n;iiiANd*>zqi6fMbOK9c~Mg7Nmv+nLk$1>MH=Y~JP5s{(|e?)%INQ%s}$ zSur)RJJT@#IkEN^ZJq-TtTFAT)ej%f`#O8!gv>*#f84DXE#~S*?!^zNRKhZrKkGK^ za@s30qCE=2Z&Giv@);7*eM_zkSS9b6AXCXHFVVeW_D9o=SU$xgL#J((HIE@C5svQ4 z+r&QS#>|9 zjE6udg|Gd}1GC(v2m<(I$O(?OJd&R*cEn`6AE%2|ZqI7W6ER4RW1nn^Jd~oDi#EiH z3+MV%sv9tnaQ6dAxCT2uh0{u|NqV0?rwh{e-wIQPBBEd5sTV4DWKLHz6(AewK_ z0za%kZ*lYYVx`#(Q>Ge+b=SR+`)argincgP?)nmKI)Z@kHc&bJ)atjbDBF2=t^+m< zanGbT)x_To4YLBzyI3cy|H@r1mSOI|^PzeVgA*&btY5R1C{r&D_*goXm}75tH`g9& z=#r>c(DaaNS)~FHx&I<5)2T9cm-}v!uee?6a@yI3yj`@rF^XV^j^K~-K*WmduQ#CH z<2|o z9JZLL#Q7JO?CZllZOYUCqLupqDDq=Nv(_ZRlPe2X+KV2(wc+FB37ogAO zEHD6!f$izfGR?d{v=$Y7TdZn(c2naw<75DjfzSm2O;FnnR1tzF81ov`%xrXGY`u+5 z@uwdJ16n2W*&3a>(XY2eHwORkE(_-}q9)S{Ss^IH!|X!vg_?-2M&Rq~l%o=qY6Y-q z8!-8P7!e1oxvh`?^?tVad8;hB_^oRfNo*5Z#k`4=s3}>;>8kmD*H5?cVclaxy4A%f ztCuP7j-uv*H&jWsK)nss{|np1a1fi_wAhNprxJxcaU@e;rLtcV>zR4kxMSHyP4`0}+KTVE(n-9Nrn%sv=9n8=a%S>kr zRK!I?j4fsT6of$t8z!PVPC1@!+mwXsGyVY=yE?j@`1esc?mR#FJeKrzBS1s4Q68eK z5D|4ga;Vc(?+~Yc6w_G&XrtaVcoNY*VRqkl7y*^-dG8b1RXYI`Q=fTSrpw=SlhM4! zI7+NKbrJk~enqit`D^=wuGg#HM?+nrvNi`IiysFhnF*Isv6if|T6US_xDxlB6Xge> z(HfbsT6s!7i*LyH`HDtlQ6Iqd)gXV|pW5zTt$0^2ZoxV#eiLHqRWJY`27;_!H3e&u6h**3v(~7|LNGM6!Zg99ys&0FiDk~3J%{!2bv`%gI z<+XfRwX$URJ=C6MwjevslM;f*0IIdr!D~Go5EZB&FRg^bgov*orN|yx&F8EZN}%gv zI39S0ZEiw`N^AVId=70&aXP#T?W*C^pmy-e(8;vFU4Q6;%(a=SkwjMYDVh?ul>M=C zvtW@ZxZZGZwf`$ryuVx|DXmUZVo0}C_?P?luHIK23iu#hA_ie2Tn@V_`nMEV9y^~* zH)iX&UL)L>{3J08D9>RW9!{bB(Mc1Cq{?^cYX-8AHQr{}BccTdF8-kdN`YfeV^8dY zr%3q{wUHpZ=DpP?cz$XLu>U7V8DSmGwvsD*z;-@;{?w^0Sh6Jh#VlMcDv)<>A2BbB zaMc1A(N)a;t}uAx5N+on5zoENF6?#I0@G+*w|(gKil zXfqQRE0p2&byoKoVAU#hqT=#oeTW_;L@!WY7UT2uDCkm6LJ1FDgO%0uEf9t}m^UzR zx47>Q3(iszRBXm8@GD0A`P!-m;-6_e{}vs=n0Nd+nqbAzaoQ`YiuWcK@SfF~`@hy_^L?^w)26Zs^zc(Y1=?)BpHxkN*Qo)#}>2 z&Ivy(<+<6}Djvrf&HhS2DdmO`-FIiZJT12!8 z1BExMZnZE5#qIG@Pf-{oT%VxWUC=V}QT0G!aOXD3-CMhR)8Tb?X1yEbo4t(*DRt|% zOl}cPnxRD@<4)DFK6u+V9%F1QLB zZaSVYfgF8tb5Ng%!g!=UuxHnv4}_2*#8lIvqVzj&QQzMm25JTOBJlZM5}JV1=a!XP z;c-3r2w11_D)J3M59>Yh?`N9KAAa$Q0}VIYlM6+4*#4r3xMGamj|{o%!wx%V^C#6H zrkC5g?qzLINvKhZa+KfjKqn@fB5!nxdxT#;oe_ZPq$p%-vppm7`$V?mEt~61C20Gs zVX#axSjC?M%eYQusI<44HWgvgI1D<~;n7Mz^I#C=i#Ss!C7iC7`{5rKV50Ajas0WJsSG#W5&{ExO`uq|6A4+`7vC@DS4Mr` z<_zo23{GZ|OYz&j9$tC^$oUYsL%-XZf}`=aX5YtTGPz4QqzVNp$YFy;+Fo%`7h`Wh zBtF-*6p`J$PgIX8yz$1&@K&W;WMHI`Ly7ceU7u{m<}=RC_a^Nu1ZD#q!iGf9f>*_I zS)wL`eyq#s@))z=hqKqoOy2zrsE2Vfk9b77L=#06UgH}VO89X zyWEee5lCcjv?)*b#{g1y+l(dhlYgWT{>ML7OD!G0bc}j?$#6?)L%Xee*Xy{9H5!{R zfS}8prG}??&hh_6A+3rfuN{Z}p5!}7Ufqe&7YsPl^daQ8Wc+7^@WEgufetyHw#*zc z5vKa-e?D5<9|Ls-!PVm_{@0$4iYt=ThUJs<&xaNJRlYwCf+S}{<>t8=vSKoQ$(gGup5nUMvgrM3x{Bk7KqQ+H zCeSZ^9{x}|bVj=zcJ&uO!fpU&J0|^|sg8eQH#wn1ehwtn_|X2-7dB`4(q%{R_HJ_U zQFu>W4T;}lS0ZDt(W5ElpHN4gHuRW)(Efmoo#n5TG_W0ryKwHWwF4D(-)zjX6s|{c zD_Nn?`@_>oQxPuHAkJL}*pcH0%<*Ji|s(ZB0$hH<>B|zE6g|XLGQduOu}DOm56gbsq4mY zd`Dbf$9+Fe6Ttk2CfThke7LV&BP>{Nxh(Pzinlt=B5O;uS+Z-xSVC(CcmdEd7^|5Zo#rG*r7orgfU0l#2;H2T+KaJH6Y+t%X zsbU5G5?8CQF?@BRQLP%1WQp35O^o7zN>1FJ#O}pf^fXx*Q_A!@UhBIUkE4k7M!yj> z=%&=}RPNWo=@(ZMLR%f!k$Ybk_G>l7BW?ReB?y>)J8$Wc=XBbaO{JAQwm&dW*CuR= z-GMHJ2@EvOI-S65(?fZguN+|o8)8J`Cj#+8y&+?~FrT3faCaEJoo_DeYR5*BVgn;n(Wm%q9szTG7ZST9sQx2`;$La%LV zeIza2eLUl7e1p9{wbFDHePg$Rha%U<4%hiJmUPWH-_1WjaHa(h@?bG0b3|JvAWS0`_VrO-crq#Ez1J&=oTc|V7?!2>Me zMQWvt7@FT@c&VBudZ~%Tqos2-qUz8Ou$cmbnZ()!4Mw>b6!!(i?R&@dnqe8NQ(9!?KGHl%5uGFkhTR51Bp{@1Eu{9D|Usg6A@y!48woU?+ zGp5N<{H>qTn)79E1~#+ZfZ&fkmXx#~10q*{k}->uC8Uw09+>>ySsV=WFfrs!Ak>~* zj(=tHc_>RfyZtcxFir=ktDj$auY`Hv^P5H|CnqPAR%x0Bs(z??YkWuk?9$S4#`0*7 z>X+j(t!WU6_lm=Zvf*_N6bfJgps2|+{_;+^F1qr*KqPeyh@pvTerFM{@Lq>V^pP#s z&wrz*s&t@2B5_%^r)WLTC_k;70M~%leOCf2wJ@I3NWENBJds#NAgks~lz!Pq6~9_) zBNLfV2;4Vmlahu>frDgtn9J!uyl49UJ8!e*cH#Lqw3Pj9Rc1+R*GDL4{XPyXU~KX0 zJ((TnV4`q%_g8OWIoAh|GB3O0nQ@O|BFdjfGZQ)_u^vvJamLoWab8C9YTHz9w7X{H z#%8LGD+SMGZY}}aPx?QucJj=^E+K%K={;Z~de$?K%@nPnu}^0GtercbBl7OWU?txI zGYa)pX_j_QfJ)d{`nyE{@7+@TL*2jjm+@BSRR2V{IhZQFm0Y_{A2_}=<{<-)NGFOi zie49=pJKNP*@g#tjuB_y^x1j$8fF;PIwpsg8%&2R@*y3UGoOGQ;^mB}5d8)aTFvAw zI^S&r&s-*jT@PXwT3-R*Wj#qRkvpKf2y!4NK%}iYZE7EqD&0ao6yHD|4? zDN@F57CMyxBjrXGanxwaE;Ixfw)_za^kCV86xxARev{m5dGv zZ>|*=6S|rHMhMaIJr;6te9tIR27B(AH803^v?~o&?E3AhB&UfMCQmi-IE$?~>IPzU z8}ByIhM)wD?TZGq4_Nbh$f<-Z?+a1?Z6TqxgFWg*Et5;2171LJ7DHAFOs0Q|$Hqs` z;TRfk-W1`z`GZw~{wGq?r1yL<+fO@-+cH<+LoumG=&LW2+&OVYD=M6|*H>S;#&C9C zv^Ag9#*@XVee!^WqrXyWmJ+5I7{^rTAFKUVp9dm~w0jdPNjhGDF{COhM`nKwqKe-l zFGZJ=o-s3yRX{UJI2R@7;1x%ve!`d9eCd#{GISZ(MQv2$#-%Cw0Q;n5%W1D4BcjQ?Dq)+T^x6BL>j^%%)tLu5iWc$wJWcc6AY5#`K*8 zc1v@89z!DCP}8JGjD{r0(widiRPg4oV7{0&sKi<|N9iJTM7z>YXQuPNc#nDbU7gy6 zd#DcnbV66ySh>E}hAlO!>kMNSgS7xFWroq&!9|bOW;1^T*t8W@hQ}`=;af`ZCn*Q^ zy6RHyheuenZ&H{}XJ>q^{^8d%b|bO~AC0JnjRKmfc-iKyHkV&CFP;zz73De|GSd5* z`H^1y@c$m@@VJ=nt9^Rnt1;;yR0;&Vl3I^7)9da%Ge{J!?f0enu1hBIx>W><&}H%= zmw^^$pZX;FQoxbbd^9&F5&7)0oGH(rCsE>>iHw8&H+Jm{iC5Z56uZH{X%3HxgbZ)F zz+*k-sRGqDpz(tYp1RUAQB^7VEw#DAx?6QjPHX4;%duZ&jgc1;PUu?3qb z3idIAgh30AErT4O*#B4xt5W3!^}bi{WBVMP9VxhTLv;CJRKqgO@;>j#u+#5D?s~06 z00Da1C(&4cr9y_G^&wVUa)4)`>|ny}X@vbo9M$j`V`!NjnIsNjGeaL6hmmdB?)`$P z^>%vXa-O>FUn1X`?fcN`-dM;w5Lo5XmTD8fJpq&Wo}73;K;lO^Y?+cw55tO80aZ0e zz}oyaoOSt8#R?nj7Jvrqgel~hDKE^fD{k`}5d1VAt^2^xORZK6-%5IG=(9> zP5-%*MsbV_RV&^CYM)*hyX@%bq<2$rtG6lVCIZvCvx=P?1TIYxzWE|MC( z)6)Ouj6Ly5wcv)?=F<$>K(x|a**I^V_(Rofny;{u{rzR6Y7K12Kj1HjJAd=#cZnCo zNrE(GRRU#5R_}Dj&&92uUoE0)#Bs3#_e56H7;$F+v;PX$(Zcgqw-bk_bcswtfD6{( zw|g2G{YDu33@4ZQR;nDo$W2LcfJGoe>Rg7wfn& z5@$3X4=gYoKzfZV`sjxb5nOD~=X5iB5d&jhCR7@-;3rgrZ*pp+l@DKQlC$kc6I^F> z9+nvUf2Z|I9MQ{?$A)Q22s%CzRU+hGfbjOecj$MV0SErN4$;xHyaEj8{{6$s1n=|e zzTQ_7BQqKqS7u8*Drg4b#UoB9VM4lQ-z&|ogk~=*@RQEYMm>YAm= zMe7tsI8VF*zkWiA1HG37r4}*CWzQ2{NE)Vg`f1rY5C8XH04or1#FlfPC)FT2AY#QY#>S7cTdu#}S`-!7 zpYOZh49C+dPU9)C&vZtuMEvPE!eOIB98b=DoB zX5Nq|vK69wWKwXd)a=C4AdWbfU`b%Nt~nFW7hip42kp;t0)%NrF)IYM&`TqPpmMj1 zxgiI@uT#+gAdN|?ir{7K!y3Rq%{a~04fD0_w%cZYfb$gb{>qgfQoev(AgnGxf}Pat z`F7%oCtLGoEp5`6u@*peo+J{5>_WL$=jT2jWE!X27z}gs)*ILb=bmSGKl%@wMn8(k zrQy;8*DCNA??Zju=?X{L`3zw&D)H?Jqn&%|@xRw-0c6OkPNo047(N%T-9NIPW58zs z*7Fyf?cOmk01u1xR}PXpZo9?WwBNvDIP7VGA59eAq+wNYOQ2Sj`dd=L5`j}LT!}1h z1x!>!-XWza*Ps5|(=3i%R`sQbC|F7jORReBo}lk8QA_rzXgY#uE?8UL=CImY2fV2_ z+Hgac4bdfVS-Xu}|DRTGfH*S?RxPTqPTjj% zVT&^R?^|yWNl=*4Jc$tIGpO$_;ZfL}wSUfBJM_Q0ds_93nWzK_Wz!tuO_aJk60~rewl-nxc$>x|BaX;7Fu4eAx=nf9 zwI2Jwo_NAG+jtWf#+AVSuaja3Y9=Y&(1;)aVVPH6ZsQ55>d?6Z3(b%$38uh-y5++f z!9Y}YdkA`8()|89ZJJF$H6B1pjuEjURev2|jHOWd7Z;)2CTGAVoAk4HKX}LO6Axo(?$LyO;@wTFRvU)0)ru>YjBgn@MWB#3dx zFw8&!6XqYUyvA%gguPPs)DU)6W&Exj63=uxZY_T$(QcKw}qS_segYR<)(s4_X( zH4y>2o(U<%BvKG9v1#NXFR!Y!qj6$NoqY5aR!nTV15LIfLMrl!Skk1Nx!V7`Gz@s*ao#ojmKiFL;7?`DdiCs%20vh* z3>}I+KkB^V6H;F};JtB~Cj}?s6)v^z-aGH;q6fzOG~7Z(NY6nrYv`F<+qqL*>1b; z_s$0>2~!acIQ(4ZRqJn?9tLtoRnzPI`rl&_xYV8UXxE}X*Iamk?YR43TQqx~6&5o= zGKsoHSV9Gs!cJJwtOP>7$j-auQrqvKgRO15j*iGTgeMVpl~Bu8_RoJmX&a&@Z`)@h zBr-hzJ=J7GH|FCp5fevH*uoEK8AGitKLe>rYZ?rob3{Yn6j>E zQbAQ3V=VwDTlMH_*Ap4A;fB5Js1r`GBu;ReID(SSRHG*7Ea9(Nqy=ZINs}krfX(}x zv6j0B9)sZh&fl$Ll4_gh#4vtBNG461OL@6h74VG*39ZrsA!W^*+d>@MwERi}20(M9a)_%G zcj;u0{pn77=iPVhFZbVP)xS=L_@gFd;?*QuBO$xppoC;2!!My)AL5)9vVHeEz$)j? z%1lVBw;yZ1HqC=7nhcpxS#Z`#oik?4$PggTgdzUPcva)nbuYdX#5dotZk5P+}E_vku+z{HTFkjU#=Jxm_4`UusYHNMm zE<0e$m8;vot1)AMk>SI7ih+NtU(AoT#}0$+$b$}W3;h(MMwA0k7!`K_+h8?LR3U}^ zk?rmtq>Zac;VWl1nG8@3xCjBIEp_t*hpNb5?p7^FQYr4z)t-LtX;S9GL=dhOB;}Zs zB;?tQ#F5T!o%Eso2Fg0eeGP%gN>>UW6VU$@Q)G)~&7Cuuiz4&WalQ9lF4va(18B3-vuE0cEY#JvS9cgEzEgecXaO?YCE!a}_^{q#Am__l z@A}r1J2a5aALIlob{@L_ZjAK-!u}RzLjE*|@Xb3lK7>5fuAQBF=9#wZuDjYX7hGUf zQ)e(gG7;wxemB8zn?kV^CMTz)%9+z`9tm>x*mF-DnaVASvy#gvz;&v-Q9@=iqyuR@ z&tuk+<&lXAbZLOK%9;Z=U*=52jk2S8+UP7{PeJUw4{DJ`?MZQI&&|G^KSth7;S0Ms=Xf=Xwq$>P_FXq*#{I>er4xnRZb7U7JV@R*+l z@v!uR`XtFZVC4(uSV38_U48jwR>gSF<^#Bv+!sBUUW0#jeZzpy05tkHs#lm>T!)_X zx^>)<2Uw>roo(UdNmi^hshVK3lB?)gQMb(Ai$*uwszddG2{9mBKMYU>PE$&$iaH~+4uFpP zux2rkWx%u^Lm0o6QV6drGg_m5i4DHK<2c$~DpAR+S6+0HS@|Nj{y0Wa4EG}Y0OCMg7saaV@~f_}>#n)N zx@^1&nZrnV%XJ}Ty^~$Fo+O`!2udnbl9IRHddvEB?_q(GGFJWLn9}FwfTs<}Ih239 zPDNbXtdtl42);}J>Ss9wMa~jIt#u&j%ZD|N0hfXr4U87E*`zNk{f!#!o*BYqwKULB zO~8mAbkIR8tW#y5fB9vGV7f8f;J320>eksgeK$(uE3;e&y!N}cYhnL)|KHp?2jRjZ z$8@jkSPX+hnE;h0xsc_S&phR%Og|ahFak%e{Z7llIP-7qKihv|31EkH6L4Y?MNEMYYX}35NK-es7DN~-Hh+w-~{!+Q)kTzu*P^Ho?kUIo95$?M6Ru`r7$&gPh*s__$Gz?{qs`<8R$M0gjs)rxV z6?g!V1dKc$Q>WS)#~)_{`}A<@1aN6Dv@GXJ(^6AVN2Kc%9?OMZfiq^ok5F?8Rfakf zs<|KKP|9u;9VacLws6(*0b-*fheV8z?q3j5C0O%|)vYXH{lTg#3wZ5#v1nCjlGJ4&mxO=cX2l#nTVO+yWl z>O3VULVQum$aC@98*lOMPFB z3@h`YLLA-qxg1k?F3w;)gr^W&nfZ#_x3x|C^l|Agq!0uy$ZWj7+$@b)O|kyGgU2W= zy=c!<#!$vl#%A|lV~YcZy+;|xv%E5veO<5nZexDw!`1=KalB0SXWfk&>%$tuz;cY9 zHTG=3;?;ryW(j#TJ4oGFjqO^}|3&AWXQl1i6GDXqtBFEHOrM!-fJ}%5UAx!=4?JL< zxn_smcD1=vSb}s}qk(xKu6meEpL+T!+kkb;jg{L{97{nQ9RuKf&E7WCu*UNj$zNF! zky@;0uU^)=O>2iccdYUBqH(uW#0HQPX6N2LEglKjM?=5B!LKNzwBfWEgc>bV=5lwB z98pu`)bGF9W;SQ$EURR_i!=i}R#^^_)1YiDK=>`bItfg40h}4nKl?NrK5C*3|7C;~ zv}kEn^YIK2vmj9amsH#Z+4IQRxq#^Ia(5g|2(QEg*nb^i;R|b5dtDG)VDM-V|0LxD z$~TnXP>u?ugNGBk*p1SX(vbqErMZac4CWb1OG^99*1Ge)4kxF`QPg)OWh7z5!;-<& zjmco*2)3Olmg1s1ehzAg&ji%Ij@7(ZcSNk_%KhrrA_fAf6L?xtbMmHdwqYOJowTU2 ziIX$-J_uShegJZ8Bksq-NK)g5er znO5$QZS1jZM}zdI*&YiW-UY2hFbw)sBH%Cz6VgzDjV9$VX^88U5VMFD9}|NB!>~ob zlE3F;!)ZA=mX~rH&l!|`w!c{m7?7~&L!-n1U!Xu=tV-I>6*m`0&3QGk{3XP%S4^7V zK0rwdQR1nIq_#>@^_F(+Z1-J%wQari<~Cr^))t#F%hId@Sd2>FISQ&uh`FQZo*95= zi1-&$?`K~QvCbVk*$zAGXsLPgG41g&<44fwQUKG>Iv_maBqdEof|U%%j~mB|z*}*Q zX$uocP?`a$NgN|k=T85}>cW8D0U%Q3G~p!q(IQjRrcH59a6uSct7=G5A2 z4awP9dcqi3}}$ggM(U_jqO=6h()c5{6rJz2SKyKP7VfD}}$$-z1QWr%l@8MPFr zsF6dzvX4Id#Qyv8%f#Q|TVzmpLA5KdOxZ@-gu>e$7SEY{-88(Nel4e`-TC<#(iqxStdX^p&6r;Wl+y@{j)f61w(i~OrtCeL zy*&I&gC#Aa6Hj2yxE3FPmtX)Me*7`J>axo$OrowdzA7GVT+t5bKAB9aM~}6m4?EoM z{o5lpbPNkAS!hRug&ot1L;x7&)*S82d1swz2M*rHDslepzv<@IT;?&<_HN#g*0 z?2Y)Y?u*Bhw=reOr{H&#v6+hfzpE1iJ_E2ivAOQ*`WKHzA82;dA8xQV*!8O>PP9VV z2sO_!Y09qVY-^}g?`1KNww>Bp$3ECsCr+~wZd&T`nEBGS*$+ zdP^i@(zVutrU?P}G-dz~(tgMR(uDvv=DsxYwmZUxl~Imk5m0 zgwg^NDrXR>Em@!9U(Y>j(@9v>QpeEhxS_4VoQ*bc<9mq}uFDhI?}%uf5N%(uu-y6# z*wS|1cA(vP&qH>_Ip;A>MQr8UvkKoF8pCLWsRJ#*AqO02U)?jD+F+J&giSIZv@46+ zDaRaZCmwU0ZNkD>Zm}j9gCya?<>SU!p{|42%gH|kvco0(HmXb6iq zUp;50wJ$5NGtWKK&W!!WCX5+pL%#gV#!Q@KumA6D`{u`yq&$`)4&y*FU4q&Xp8-3Z z@@L8w6dzV22E18&HCE|YwU#l^iRT?CX$fl~8UTK>gl!?|eLW6dDo-untK9u_kfgr< z=|{WvcUN1Q$yH%f%KGQ*_l{u@#TVDlSEyYbW5)~o`RudL?3bT^wrvM(gSounP(j__ zXhG6Hj)2MmpgadkLmR^B(cuRbvJYz)11Sh#N7kvBJ!7VQH|)FGhi8Uq=C`PNw#Y+1 zEh2{vpGfe`g@Z4|?k_uD6#HtC)PG3HnE@mT z#4GuMmz8aWRQ+kGk-6t=+$GxiJ7?NmF7$n66f3)`oP|zlrss+p#@K56+X_sueHYk>K{9jiHz{f$(g!qHWc!Id%memZw?jKozJUtlMl zb2>9Y+V&>G4d5P%tQYmsnU5vz%XlspU}#HP-)#H7gGtT zV-MKV+T!RaM?z&U45ZV2`15cmkp3bP3bxUsd?q0G1+VzNz7!uCGX|3B!=k)JrbD|1 zyI=uMJb3!?5o!hiu-VH&FDj2=RQ>ON@R1#V>~YRFKp}$i$mQb2CkuCT_K%xn*ylO3 z=FWGLm5Z--I$GVo{y;z~O|$@Vu4;w!=)=0jfD$v=qWLbpZ;=+Q!nW@MS(Wd zSq*^8)!>*|s0>M*w4l%r-=R4`E1<=xY9RZ0)cnrZ9p|tJQ$u^@IUmHC_nfm%vtd7v zwh_M!w+JDETA9=F@bb&4Px!sx+5T4J1RTWJu8f{VJ-XP81#|7pi!Zc$9(!1`fIZ3f z#ee?84mj`t77ZemGG-IvFRtS|3MaGYUJ7Ci46j#gAk?BeA;tkw8ZF~6z0uhv;Dl2mwv=d5sl~D91v+-LNmHlT zmb>p@PrmfD9e&XM_U%U>*ui`6M^w-pB=Sk130!F|(FCKix*?};s+tf(D-9J`AxeeB z>;*&^EwBwr3hmU>e`8<1|BfBC-`-Y6o5Vm=r_*iGE4;;R@(p0gP9IhV1Gyw%W$yRy zS+^LtQS+Q$;%>X_%4dL`)06x)9|(}3sz@ecsO*&+eVeVfwvw_IXz()5I&M}F@vjfw zF(%7c9PS_It8c#f#;sP?qeoYsnYLm~0dC%@e{UoHEw5^=c$h#cnNxo;84(VFCa&D# z4*GxA1O`frOPm(DNB8db(~m#djM=kL0-(-UOur=kh5$+5nR2i>i&>pJcY(e3=Id~= z=*|UV5~KrnTX&>U{1M@+LS^2oXCLd`p`G1(@4XfiK3I-hevJt{?VSch{X$Z&*{?y9 z@_3MV7jw#3JpcDO>@b^$oxT{qiN8|UMjLNxl_UfUB1GVW2bHbDj|c%`ZGh%0N`TCb ztSQQJBQcSK?=I;l8Y?GQlpC5 zcg|8`ADo)8fu6Z4(zx$XXUi7$@u#0!JC-OdY}v|51Z!<_XrO6p>QF%D4y2t3VSrki zRWZ$ifa1?o!#3}480c>uJ#x- z2uBbTP7-2L(zd-FfaExO^l0bkR!NjVhGkae8vD6V%)@<+x$L-;Muf!rZ~-wp7RR|t zc=(~;e+vVE>s~a&1bElh^hAujw1Co>Ft!6|0EDko&OXORO`Hy)rH+q2vyyP3RWUzA zc}M}yeah^qe=;A|0hv*9OP!Pa$UUe16#=~qukh|QjGz2?vSmdc-xRN{_ja2i3L0&nJJ9l83YpoF(4fN) zKA4sKAne`;5syi!bAcn)v?P2h(uLQz61v=IHxs66y#Hz!>nN;$v4`( zrF$n|d_B}H6YLiD;ax2T9uvR`-6tFNz=4BcekUT)#<7M;3&5Ce48*@)=k#p{;(YLE z^l+>u#2;*q(fJ-TlQ+&Dx5|#&iL@f`N^7EP_XjY^M;b*5EcCZj(P71lH zVF0picHwJq(w}`X#11;-U<rM&?Au|(Y|lM+cav%% z4o4v*Vd%o<{~YAJ!oTM88M`6wa#d^*&^VG9+HDO1V6C=@gEx zTlU|=#*ZIolOb|pRm&eL=rss=%a-0MeO%iTw_O_aI(!GKi+8rD+x37<_{OXm! zMP8k&3t#GsN-l`#*D18!F?4LzE#|i<%s>jq#nkj)?YP4ZvKO9t%6j(fnOn=r{P>B| zKKG!%-!KNitPlB&0llDxUJ}R7(exFBso!(QT`Wzeu*`Ip^VRBOLV}+<5+^9)*$+MB z5Hq~^3zR@aDmKqwU`Ytze&;xa&Go0Bhg-8|&4{aRWyva}VZ|jc$p*Wm`WnM=X955> zFad4bwk6lmLPs!UMp-ZWoA2*LQmlv`(%(j`S~qTC?-S42|GjcA6iHKn24J0l+A45u&)Mpj z!+~}XaCm2Fv>mCca?(4`wFCFv+uncm6*3g=ff*y5odc~e^$ekO@G}PsZ%c-TXv>nX z_Rp+U4Cv*EsH=D{DwI)sD(hcgK4}}&w=XGAx3bv63dbSWIR5BE*2IB&@U3^=AzydI zw&>T7j|VBi^Xe5>FI8Vdg}McmI06}Y$48ABV}1Mfvw~J_GK>SNIa9o~_u*zPZ~T8D zILZMaA~R#gbgNLf88}ZciONCHhqZ_SUV~FesLb-qU& zYlwutluXgkj8&JLl@(d<4SU-wZ<1A(EOf|_j)6_adAI9&{JQpMzt#HtNW4;kXP9;N z^&3#8KASn!4nJUD?b*w(yn&AnzBy5rJVs&`6Og$Qr#~cSY5Pjh5DY^L_*X*wN=i!X z-w!_mPD#{5(lCWfD!k9+EUY%Txr2?{XX~IAuO5Eg)|pZ`x1!tZJ97BXeFxrqtl8Fk zF2_UR0@e`-SpngR^M3f&I!D9yUsfl*?99`hNkHib7&zVdkVmkyUmCT>l8P9LRVi8I zG}?`@>q8^LKoa7OrS8Ns5_Gi0(dqoN&!Y7qiz4Ye2SD{jAAlwSykn85sgoB0aDOp=h%94rNTg zV$XWmWzX)mcegI~>T4ry!;G2HSRb*wwDQ$sY1w%&@kN$_@$P?~|F4xm49_|DY-`iA zJ9>YjTr%EeQt6RDW6y5f34tUD#Bf@?Hev+eej4WGSt0I>ws4`{c>VSE_XqE@W~eM3 z2bPy}KrVrDJ0$*G?LmbWNTMFDP_Nn_2`v!g$rH|$Ut3VP9{g8ogGhK%jw?_EU12 zTZ1Bu0Lzf#oP6Bz)_sqz_7y>9D-Ec>U!I493RW9PM2w`I;e9p=s*9O8U7~<1y0neF&!PRGD zMq@}^$2t>M)%E{cA-np3(rVgl;@jjxr0;9kxDkfqi2Y%7GFVAw1POq?*^QI7r8R5s z-QE@`!56%|oIb#SwHQM7H7>340!SzQ?A9O`=3y=AGtD@!wh8-KqwEjK;e|HtY_Qy_WV;%S=&bS zEte0}H?lpCrt^EL`=#Gb%~QSqznxY|l2QZl_o*C10L1Y>3+*Smt~9%Xj9?AO6JE?J zhxpiV{!!vp4AF`p1I%sT(H&gz8k<1Sc8Af&9OjqF*NgX@0# zdk+_W_|QYq`4`~=$bHB{wk`ok<_6L*03S&mL|`*9>1vnal`Cx6_r7N@VHZ#z$)yx` zD1F2PyoCK{t#?2|m&Pzz!kOB`q-udU@sA+`I&6pnbU=k{*ug^)$**Bx^INNO2ERaI zdp(BwnpL)R6_WuAS-Dfi&8czk3%bTF40TzJSNQ>5gG0FP%+sB^7*pcarCnUyx>|qMusA-?PBi~bt&32^q zcFD8qBDScNZ371Jp76YO)=6hrXT+MNrYkm4EA+qy`1VFsdh=bdt{6i}D7Dh3D4XR7!9{f!b%|#+b}@{`HT)S(|okZT<2k zEEWj2+fXVLJ(FSN?}12sR_p&)kdMJt_Rf zJGJT+DZ)-Iy0);L)&d&j(Sd#zB&Z?0J39TooQzoE`gI_LXo3v50Jm%|mHQ5suy4Qj zj^(4fZ%sH9S z_-McW``F(eeaPyua8i#mmM%*xPdgXHSz|tbdq1RxVe##4hU9&2qh-Iks{B;>xaz1+ z_bvqWS&H2cNKh+NS-k?%U#Fw<*9vLExbb%GX{WgnU@7`Q$D&#h#e82OZyZXVz=i>h zHsx6_gQ1WvF$*KO4?g$>}ii&#HMgo*0D`% z>(;3Yd{xx8qErae)dMjE>`2&~z4p&eZ-HnVyWke)*VXk%vD&n1rr~Q#$a_(qkpp=T zeOI{xJP)M7v_&H5!ZmRq3Wp9IY6}-EWPZRbGv3Rc380K*g^kRA#TxQC0+;+@=-7Y2 z09%ekWZbyXmf5?d63{pGzN_dISlqJURnzNQ9H!i zB3gU;QsNH&D^E&Zq>%8z(}`eu2u#2OeoLmeY58LrW$8zSxgGW?*aACL*O z=HaOE6RS^4Yo3{waR9W)_UPEg`u5%v5h$TMHPW>#mmv&Lh^v}b01ElJZrwUNc*ue1 z|B2lX1K_EGb^qp&ib?{B_+${q#gamxRp{anq$ zhsd4+5n@BsD2o=&w-p!_WfBdsjB^fZzgpNeEg+GLg4wVuN2lGYRVySh={Dt?>6SrM z%B|Y6Fk!?*YfQ`dZ2&>D=FFO91G69qwjsgWSxBK>7Ul0Y9;K$a#4-!M%A%k}S*^*)meGMi7ba^(m9+^n=*3X@7-@_I3;xkTjenFA| ztR$Y}>$~lmft;LgslmOUoDIJ1wPF-Qv9a(!A&V7EeS(-Ae&}K7`0J9fF0uO{PNLbY z2C|8EHUZtWQ~|wu^|GS1t1w{0YB)dYPhFu7D!vi~ajQEg(~bw)HW z05ES6vI>d;P_Bn5Urlwpj;%5fyZCdf{W`Y?V9K-7FUJu0IE?$`^7ir@uM-upvE{cV z5FQrrt4QL7+=>87om_I~xdQYOpUXT@lciW%sEB#wTeHRJku2@E*Is7>x^{C_04$LF zCO>9N0bP(fZRZ26QVS{20z~sHzdT!_c`}-vcKq=kwzCuiABK2^>KDmX4K={5S+lKs z_dTpmogB}URVI-jE1)VNfeA>%a43z{fd^Sp5E05c_+X?6YgfYqXt+e*m&hbkS!Sx9 zM0(<>P$3w~1lXocn`ryd7A1*+fKqwom~wpsCI|d4jA#x_?(|tRgx$CPC8)yO_?3H0 zu$XV$yakK?G<*5gS1paXk;;$`@y=v%P*||WI(6=B&6_o`(PKZi+pfFLZn^OWXWHd5 z38C|GtU2ruZBE)RVdAH9Lu{e$WnutD-*FQ(f(6xusekw{fAO&tYX-!d_UIOhsL_{d z8Gt13UV?gIh?Z7f5{Wb^Dk=1V+f<=0iQ}DC0Rcw4QUqIr{oZ@;!G%BH(ja1avIZ8w zK)9+vt6Uw2E&SFV219ru2W#RL3m03#`n9&l9(xcjoJ1oKMGrU34K-G0rZxcdeGOS{ zwrSJOR;*ZI>Cz=jjO-hzgS}h>YvEgN0X4BUn%>7dNL<-38`C$2Xg4dCDKK6O(KKxV z#HeAgs(+}^82=g8s%0zt_lwVQAD#pfp$nJ`r34xB!LJDr`Z{_w`ToWjP#LOb2@jyU zJLmK>t(bb>{Kr4qZ~uI+9edKrFgkb!0PEHf^B;+TgI4`|rd-CZH5+8(BsFTLY(;3J zQo=#+NnVH>ue#hBqZkW$Hd3L>HriX&>^4dKx+u0wJX3p|bS)4mEpLQTZ%#J&>(>9f zmcSqFh<-)T50F;{5+tNRM63dI*2|W!vOazLIHMq+;A#U1)dOol2*3H}8*4|daD~Jb zL@F>G)h;pRZcIc3OBOGN0U#|fVOG;?g3(l}^+sR-oC!dTk3s6*r1x#yu#qQd+Unqr)7rLZ>GC-_=>e3P3&0D)?kqBNZfOW%wYEi(C`LD(D9=WKO7`h$l`|t9~Eo>V(%nN+WYT+ zK<3XTcEa%|*ai%LJRpcJ%K~^Spm_HZl_LMPnX({;YgQySCB?~zt&X=+L~38I#N@0) z(lT$}JXTMvA*#`Ssr~U=sC~@$Jouo;?+oYTC${xKgs7^G(_S`vVJRI08T_bEBCNOG z7-@?aEb?>lKY`eX6C(Hm?PG*s12!Flh77h`qFPD~ph%aR7Yd`T$d4%n`YvVb6dqW! z#+r~Tfpxye_seh8$g&6xte7Bs_3L9DJ9Z@5pHzn2ySu2bXdm@xv{$2JtS*Ml5sW5_ znA6u^d8PG48lVJgF+opPYIh3tl=-bG?7BJ*;WthA#Tdl&)SAS&Mt^ zq3!OPU$4GB_reR-2p`~FVy8zCYnI{1?mGKK`k#2LCW-x4yn9~(L-4-&W*Y8OtS>+$ zS-QR(=nTCn0-@)d({Zm{Ncvf2QItN>p>o?r&(_Sp`sBndd}Six*TD0p5jxQZsEyck zX>(fyiI(TA&^@|0w)yk^N2zTS%fvndm%e<6cWz#`ttO$3v@rhM#)m2%CDxtea?}QO zNFJm37Vm%XzU#@I0ibWAvEpKn`}b5VD(QZ?B|r0%Y>AR=3>q}Zn&)f&BKU)mzy0>x zy~?w(2U@yf`KHx(RR^alwb3^H-n7)@JCo3tij<;=sAaSd7}Wmr_rD<_(ZDEIo|Qq2 zUkt1?=5`O*eZDkR`!mg25wUZG#C$z^bhkWWdl$1Bk8B_ozsIXd_ZZ;vUoU3jOP4uw z(Lx(Gd<28K%(B3cbqJUupZ}=OR02X(nOy3O6vU;fvsv25{x5GR!>zC3F*`o zj7M=Nd@L|ZQ9(%@E&uxUtg1^9uae5g)+1u5CabzaAZYF^py@OlBd( zsF^f1n1V@-?n_8r=Kl)L$h=2=?9dRC&UhJh*lwr?7vvF`A?N53b7 z!ZUg2Ij5fP<5@SAu_E-o)qUQ#9Ef9f`7!0iqz_5gxiajfjf&OIr~~txHnsx>?T1Z( z*{7f2B|*K9J@!~zx^lHmoG{U{iRPncl~|e?)&wXwUEp$ke1e8K}9_Q~ zU|3Ilvu3sB5qEv)fd`RAa2-+cgyeZJwgr5ynh0VHnl)<{Wr$=f7LTMDuI>i= z%EVNktj^b_6{MEml8hiZa^gZ86+mRu$hcRhMRUu>GQD2M_Lh$^rD2qs*SxtEL4fPF zZfo^Ab+SB&QclChR;Nu{%c|ed(nxU|!C0*X2BH|zL0Kt%k;rJmY)D-H#pLNWdD54v z%|_zyzY_jb9;8&0RURHRrPjAsZyWW=r&bJemtHq7D&0XckW%37!bifCx>0W720P{W z6Mc^A(?`Dbrq!vJ?{0ukJoO~sO$uZ(gX(_oGf5D31cVDx5vaG~naOyv0O`m%=bvXk zIOb?j8_Z!@S#$WlCsOgVwx`ZoSk^)kw*VaJ9`fDo+O8?q&-)X;v&a`F=^{oj0$RPL zLE=j|&PJd4+=CC>ItYKiK7Bx*+mY^5qHeh5rAt@Y*VCq1Q(0S6b}40v<%{SiH~{FIr3l-X^wT!+Q5n$w0l*yGKtCG^GXikb(PI zllC3lU282q+a=^+s7u=095Er`{Yby^vU4nlYOE(Pm4oUksA_QPx$rFeG^w;0;~g-h zm0ipDi4$z#-~+9kI>qnv!cyc95|d1f7-i^Ngr)z9#~x#UxaS@l^VM{F`>nU_g7Yr4 z`bb?~|KKwlJAR_|S42SOayd+p8~awWc}bD4-f7j;xGTqK`i5(+v8P{r1%pb|1D5uE z&_Ew}+lf2vMM+vvEd!9G9TTbrXWvzmdr<#sM+`)C zKYPYZf_`+dI;^T9L<8JbC<8fWVL&wdi!a=cpgAix8ObQ6a0KJP424v!>5xE3lwx$^ zmtWaRa>_Sj1-n~;x|*Tpgi*&Zo6^ZgMEGFs zFayQ2=0K>|L*&GK%2lt_vI$q6M=XFDGiLL2H6VNkw?;5(jbK^ZfwGkx=+n`oZQ#K} z(Oggy`HH6!#F$l=1V+-VWPPFKHp{eu5cz3yX4=Zt8?4V>d)b|L-({Cx`cs>`Xo2;w zGswzUXSkXrD`A|c(r53ix{CPcN<{^;*$G$Y>o56{-Esc|j7v#e)BnMHdhV=uC2KiR zc0O5aS6i=a($W4PAA~6#yz+oYNbaH3mRiNQ7!RbVVWr-1}IKep)u|kSCiAI;>OM z_O^CInYC!vz?LpsYUf>iiGTj*U!pQWI#Y~9MIJpegxlSLq(GJqms&`Q=o_xT)&}+4 z3#L@2f{`9vI-#bwkEVAmByS6hU`5_|EeNyw9$mqtFacmS>968Z(3r>s2}1v$Ys;6f zu-D)GpLJ~49?ZMJvbI^rhk*>a#AWcd26w5oYe}sM!Vq`}QAr+z7{lgQYTzFbq;#tI z23yM(EnK`h0V67woi*@dx9~~mipwN^XQ@C$BN27g7b(Dg`wp}`Fnb=}63;&O9IF39>)5%iJ@Uk3 z&d8}R(k1cO-9haIPRnMlXQ37$+L`^~mYZZ*J}(*zgFk#S$&sTUDC}e z!`$B?YkQy4``BF3RAWkdVonWyA87 z)~Qn`g5zboo2Lw4J&m>sNUUpB1t#0MSW|kWL>Pcx-MU+Ty&PMD9meOMe{Qqp%(i1s zJjqrUL~O>a8J0;71#hop`;PCTKJp3y-=(wADMQNFZ@+?RYl_=t+g45N zqfwu-LO=kn@0Ms>OxUh~7;@htld!pas#Cwp&nA4AR`Qud+{-3@{=8)??YJ|}vY*oaRrnMlD;~DkL-?j~Z=xcxn_&f`9~|gn6K?2+3G6`(o`SC4+x0Wtx<*$}iD5 z`nN3%K%*utZ2W{tRtLt}0|CVi3aNnlT3ZT15uv*q)X%ql_Udc(i376lpaC`$2B3XM z)F?FTm~j)4p5!yFW3G=W^ljfxRT-EXcXFkaN@V3qyNPJ4xk$ZYGyI201KYWmh30(? zgI$EhYFMl7qR*jo&L~AxnV*|&4I0)3@u8WL{NE9iMlESB$POrtl|%z`=FhP`yLaJy z8R9>=Wr3C%wB-=8u(|(lOl0VcgvNBjxX#9qun5t=QVDwu0F16!01|TmI{<$#_k(Ox z5jj@qw(u<#PVz(NX%G2QXGv7d*0yb1n?82|6bTy)pE0pMP;BOHh0xw%zpc+#zF)3j z+q6+Yc((|x7(Q)sbCkM=>}m4&C_&_(1p%qsc~5)rpD$R?{SUTJCw~(q{19Lf{R~z~ z+7wUUnE;r@47rQaJQ|X|ai2i$l=7&E1NUSwj?&rc)Tu+_s_xdJc{3lLX_*jnZe(#r zYKmf3=18{Lv?zPzAJ5vshmWw)CPRpjYhH4csCnC5fX5oU^phHKi+p(K<>e|!Be?A28TeFQPXZ-dE5U=RK0&7b`jV6w##HsojP*T_c z06+jqL_t)UDO>NJ^&$QT4%*+-{E9GFhH{W~CRWr6X0jBk>*J38KDS`hLY#A1PHz=7 zz7rr5WW0Fcd=G!y2p?^hV-yDi!9!2$vc5<_TO)ieLj8)IRRE$ z16GwDo*AT(<{Z&?{CPrNB2tM^x!d(SVP)^PsuTIZG8oKs`Nqq@5hKrH3?IulpNqR* z8AfHly8Z^c?azOKSBxS_J*(8x5ts&fhlKFCZZyd?oe!XMVmt-Qmq#Pf>3*G8dE~h8 zYuWjkNVvM;*FV`-WUYW7iFk~Dx#Wj_wY-Q*FdRh?%W(NU{^S$v&`1AjZ;YA@&MQOzY6ID5yqX2I3_$YsXIJKQolNxa zy?gco>oT1|rj@PwrMt{T^f_)NfW`%x?NncVi=sBcT(n1Jjw8A=HjvV<_H zT9GwkWhK3Tx%6W(1|TI9rfli^w{XqLDqa`;_UvWrAu4kqBK5Py{yKv9I1K z)vb(A^}7(G>pZef{_L`!*ytbr#8wo#Waxfgh`33B&4BL}Ga$90mH|lK{yUkfWff!1 zpCfC2Rz>AnjaLSV@ete3oH)xx{{7JXxs@|WT81p{F;MxL@LQ8#n;?cjvPdX0WA;p2 zwRVl=5Ll>e)f%p$4+Bx}PQ*XjDE#I7rB7|!w7JKRx2_$d#FO??dgQ2>Ab$6@A8acE zj`dd{;F18x`!M0{x-N!J{`%owUCyaf&u@3>FV{06oMe9@HcSy)iETiPKV#fDyXCjP zwf{lAnWLM%UxeOn;?;xA~;_LS5M;}`Q+$TGA>}>PC`r4WK zGE_ZTk``2fQbKXN<(~1KP1}{MS!ahIf1(}q$lvVc_dXJ#--qo|i2uFOb_r6q=)6eP zwyI?SlDFqNXo%&bn;hJKphZ~82$`j886%`G0Jll!mx-VHOE0}_%3PN(gQ%rTa2JG2 z748e;)E}to&&C^^mhjBXd2_9Rw3%Wo6ktfj2w~QE@CHcuN`6bE-56C!396P!Uw&bS z9W~s_3)XsHD5iY8FA^Tx=EKCMtt_e+;SKfD9*D?do?}IWEZ0g73NNv@R?b>!r;!jU zT{?YMx$fG=eOmdiMYK7KmEgjK3)mJDRI<=UeLl`+&7Fgasje+wwbJ(J(cRv_mw&}7 zqWS?FVtR2AeSyY-2)Ky32(<{l-h0?#huH-eTwr?t6Oi%)Fx!x)g63y zRXr@5CrS4RUuidA|9|$*dq>)8PI2##xda2CrxKq`-L|V`0Jdx7?2?C2Oq#VLB3hIB z4M6A$#|sj!M2LNL2ZEnE?JHj`=^3rq+ylTl0G-)91RYph6vnEllpnqO?!_b^Jc8Y~i_0OWMqtL@MRCBp{Pe zCz!AZL{aJQ9HPr*WGEIT*zm(`5#KQtQGNu*EHfj=CQKY}d$7WN@ue5-z@bAJyS!FgHFVrv_U!J= z9SU@3sy9XO+x!W;{sD~@#!@;_K^4wcLBWbpeaNz*n0A;oeTFr`t|Oc4Yl)p8uc1O1 zo!sg)(60ZQ@9vG7Bp|yC_@W4EquwyIzqsOZyZP>W45goN@|m>qQyL?hy0G7B?UaRD z1|T`RPV8kT4Y1a@JLTo(VV%0%{Z+w$@fvI3Ndi!Y;nuqK>#bj3{PqD6|2SQVAqKxt z>5nrHu^Z#}gA~@HBdp6iRY)0S1u<%+$7}vizJFa2Qk9Ix)&hOdM_PV@4F&cZ0A^U$V@4BSDf_zGsi#)(xWHkkxks*>}j#E`Sgo9uFgqINU?XI!7c1 zl0hckLPS~8h4qXxNdbQR;~(24mt5jZrfa8L}6Yy~1PvxgjVhz%V&)PDWz zUwew%r=EJsTD5A$O1GHS@~CZ8v(#3tTVX>F9cp4quD|Yj+HUK$QdGRX`|o21b*}^5(V-E}fB_#lX>bAr&t+J{DF#$o3 ztm8Cv!I>cYW=%)}1QL;(mcnIjd~sE!r1-h28Y*_q#n^aa3>?_s#(qA*3KWW2B6V7~ z+9*H_Ljr(A;t(V-I-&N@Qu3vQ`fNb;GYg&dWGvlh&6{iECQYzK%a_`6{FRFl?e-b4 zA6Xk4ST8&k`uFee!J9hb^Q~3ByM7`v*EcB5u0WRaiSPH55dY%B5_|IRPubh=z3rz| z2@+8;j=0EQ5&oB6ddYhA>SZ_FaD$zEvP@JY5Gizvdoc%M1jHPOXp4YvD+F~yXjuIY z<)~aq1fG2INjvn=L+$+Y&-eGWgh8%XubxetHq99n87hha5F>QSB^Ott3P>CF+1oB1 zGts{KVybneJV*Q@0x1Y3*jQwd-LROso87Ew)RosJ*h;c{9`U`S?YFnzW1Mzjz>ZcL<$UVDt2FtDn1uI1b05W$FQDMs{&#{7) z>#R%5_IAKN=uruknxQhdnOzhD(-8X^-Nh_fW7m}A#h>9VB_R8Hk^q1MIm_*ARhChq zz|{B=+N5%AH#sl=V2tKqfXay)cg>+Px3_)jk|M+P;72aN9tfggoV6VAUL4-JF0y z2;Fs3dpWY>ZdC%)5bIZuJQvNYfUX|5EW=+NgA3O^FP}HhW_$O|sPs+xBx>(xMfd|G-mN;9@(r0e znfAcLGIWlD#!fjZpipm}z3#f}?B<(qj@=R6Ni`5a_i6%aLQqzhIY*?Yj=@9C93zlGb)t*%kMpY0S;Vuz# zX{Un2N`;5Q5AKtffbI>YmNMAqpf4P;|4;~7JQ`MbqGs;H$47Byg>Ni}h!>DEe$PF+ z`dWAz*60$SW)Xkhr7i5!Sn(~~X%#9#62II#f;v%-!UVE*d+tQyvq;*dq{$dJd<3g!b`bs1h z_mHmkh7KL-jEtCp_GA`R&?Qen&GULrG9TOjA|w)}u)au?2!ucerVgZn=k*{rh?QYTDN}2`Q3nS<)G=?~Wd4|0dbeNwirx zYN9k5Kf(xlLnZCU?c$2jgo>rI9`BT zM_#u**kniESNrT%T0jU7#P=MxognSp+s{5_`?1=Kti%hzSDZ0DCD=?MPqUi0vL9c1 zseM6S^Y`9)+lraYN^aqpO%ZFh#<_s{rVvjd&(Tr7m8ymF${+)NR?Iyy=pU_YMX&>b4#X+!ouX~hs^Q}{xez-+xe$apb?dl$pNOu$M-a+=@WBV& z7*FRaU(>lnP+4*p9fvF7Yp=cLgjs}oG^34o*<@(!3ok|71>k$r)f z4IS%!p&sEqfickUqM{O8ylAoQJ8)ljBb0Z6q-RS>g{`!~dj92CUbYbcrDSfz*%Qx-QWg)I&sEIn&Eb)NKSF(K z+Mf9)JCV!=4XucAb;L<0*@vG`R0~alf$U4Og_cjrFRzsVBw4q`5NtCcv3hXjS&C4` zAgl^}nnG-rtX^pwMC?JlBH}(ILFB%#?gV8R3%3=rI&F^rzeUq#Acm!^Vyjy~RW(ep zbCstupPmiz-vASknU+alnt}E>p=d>@+QSg6$K6r}nrVpnGjN$yPWcj2Fu(ipNA@+V z`Va8G{`iB>Z14dGyUtz~{QGLvi_4ru`MIq4A-BHDRbT2@0hiR@^d?AIB6W~5D^!6z z5(0=3;6}E}l@51QfBzJ^e@UDYArRf4|NQ6f-luDd%%^d=C6J-nBab{{ue|b#-yaCL z_93#L%GQcqZhavxz#6R91=|1dkAJks9(xR;J;F{n;RFv#wdbCDIwPQZhB}B5$YK1q z@6gsplM|pv&mOj#xzMFcS3KM{;1)|h4BF|Ui!QSF-hB@VL%Vp@;}QX#p&3UUeWZQ% z!FyPK^9)RhvTG_nLP|ow7f1nekwVp{y(f$rXV?AWmzGC+4Lj%{8};eOHg3X~M7LaO z^@;URh~aP6jt`}jY_2U;T57Nia9|P4dLCI;ul@Oz_Pw*tk=?{z2uN?^*3E!Vh>-)6ya)+E4hAY0BATj$q1ruv zyvvH_FSH!#p2eeTLaT?j)XQQpK&p>a*pWlJlyF ztw5X)1j+XzvLM4UMD^(qc1Zvt*}0yM_BDdl{NU`f?dqTZ)ULnfCK87%xA_Z~+T<^$ z*ckljm0Lc7W&P(9##@WFt?j@Ahgyd=o$REOPI1vTOUmf`68^?)^ZbldH;%hiEp73B z+d>sDCCL#xw zOPo$}eLdbD`}OH-4RsUB}tT2RV(rH zKk$enZ3bb&Lx`j2pZSN)pFP7azveo-@5bxxq90vk>t@fv+eJ1ln(wjkrlA!tx9Ua6 z#xc4xJ|-EQ_=h{}n}v(4HN35r5fVQ~>o`=)1(@3ODV%AJe9N?ZjUtmNFK!GS_%$2V<#~b9LbP=bv}) zfE^|NdY8s|;wGa()#sXPu5mSl)CZ*sas)`-5I}r`q%r^f?{n^+80DT+7KXAgbsv2A zp51oaZLV3#CD}_NNbRPyz$>x%9*L@kWirg4MCmCC&iq8{E;Wi=CN<22>=hePHaD;9=geceb#V+y{mP-J2-g>N3*REq=%058I zE==ICPq@FTLy5RV0DZ-PC~y&$=Ti}1mj!h~4Mqg=xi9A1Bbv>KM$^d_m%(NY2$$Qk zxz$0moCN}XVdNWj@-fHSG3fu65pD6y+4Jn1#S5+fK?m5wPd{Vte)5?;^!Sr@^R2(P zp+kpTqxwxOCoR{qEozaic8`j!qqYJP^zbRrrY)ZcfGyw#+!amSpDmV#z8j0g!UQG-xd-` zNz$M)>@6z9N${sq;Ex!22eFuV@)Fl$*8I8FsY@68=Wu8>L1@H+_pW3&mqka;npfxqH!G`ee}_G=9y>u zxviC{cmQG=BxV<}-WpV961H}~=0T{N-ZKVE{o%uhyCI>pCO|_!4r=^4ij(= zN9oRdxh)O9&N%%HTZv&@A}9v}J!2=r;LV&d!y@?7r=iLzA;v+KByvY7(*WO6MP>Zx z8~h-6at*mE24HY{)bL>*Ws$e;%eIlz|CXxpZ53O~0DN05TitTQ0E?~gGBUCU(J5*2 z0O-)Fxt29vk|Y2kB4ApsBD%(!Itv4}h3NKH;=0$dJ*ud(Vu%{|$hS{DTL~#_QYDat zESgTE=*5RD?3e&q{#R``c=(iI4$dyr&gunzP-XG3sulMYa=R?Q`5bmq|k-ArP)?W40 zCKp153RdDEfx0(?c3@39DV09fpK*J>=l6 zp?DWv+jS(M)?!RMmV1tc4AelIsAxjr$+E9JM*KGog1Rt5aHr<&+u+)GiY;Hg&K`XD zQCICvo;KC)L`u?*2#7s;_jH5P>u$M~u%m5l9b>SRwvNaElD2UO<1$&kc~{lLzniv9 z`2K8CW(&_=c-9Xrm$v3V0X^)B%2m>k)Ryd!3Uy5OHrxsI3&X`-y>diy5$Idn7OmVs zuc{ZgwLhb8{=x;;v`IrOq1#83dx(dZ*vhx6o~-&@D6bf~R$GW-I*2wP?5dyGS!Y#O z%BpJH+ABm{1z`{3f*P^GG^sq=BEmVj@fexlB=*c`gIJ%{{{INL^OGyCu(QyG-b$Fy zcR&5idhFfb?tI`u`(pY`dkKH?U;O$;J9xxl%w&wJ;>-|4o{|+`LHlSMQU2y2d{^wc z?w6#$s;xp1m7c3`Z3ljc@CMQTyYIg1#8oSQfmZN$-g&1rZw})Lc(y}7+W04o30dkZ zDxU~ ziE%atnL59Y;8(@P3dj_mq+eo~?H?Gt$txfyC+hyESQ<}1^R$h8bEMysq45H-6jL_j zfFYjWVE)2|mQGzt#1y9rR30xHW5NX(5ck15BA=#JlWd^v)Z6#o_kiaMxafilT?+8T z^Do-FZ;Z71ZCaxa#PCvcXzK! z8j1{4h!%qW3UY3rp66=_pi2 zj1aWkx(zJ@iAIEUuIKc&r`3O1~LIPpiGObg^C-#Nk$% z$;2-wlx`8Lp{%$hMitf;UM#u-N&^N=K7@Z%rZ#P>h4x>&p0I@kmS9*bzK(?D^E%~hSQ>7Z{6(_C%9ahVKH z8QYB*(?^at+#Y!Pc`;CJxU)ao*i>th#GXyHy4RrkYEnhFlF|)(=}2g&WlJLafz{MW zKAG7^SGE|8F*r3gSCis(J%(wrj1D1Kb=&sBS`f3!WLd_dImY2`Z(&tEr%9Et={pFy z9p6NR6Su00sBlgQkF5+sQo>dak;uSOKeuTU%Wc)hKAZfdT}K+!b1`_j=dmX(yHQj7 z#f>-HJD-lRNB{m$JO0!kSTl70N}np?FG3&?@z*~kR>~ouOgd5kH^hu~K!qx#(hm_+ zC#WzS6xK)FMs(E`A?~R6F~$&+#iU) zu7_t5?+wxcy+@u2%0(d1^I`^GA&||eQDkWZ5@?_Q4u5*}>S3?G@+v=-)v%8D<>JMQ z?JA7o1f?(qKA$L4?wg~=fyZHLlm#>80ZB$as=f6{^M@UHu$_0_d5&p>Uq*lS8I4wM z=bv?^m4Hl^u2^mlKK@rDGLwf4jy7n;eoguI*pUyQjj|;j5rQTS_3@|!)sAW*w$tK8 zC*ZgExg)8q~Mxvu4?H zxcPcmt0yAU3MFpC53T-W6h&d!95B*j1a`ak)Ylc`AaEDY^EE2B6k{zRe6TSH2|c(Z z4MZ`EK>gG4XwW$s)RmI(CQ_oh=pz`e1mq#q9x2=Pe1;WBq$vx2qMl_TzRYXh!p0E; z{*tS%vLlZ_&ThW%UYlRM!Or{H74{!u#ovDS-FDdFN5VXXp|8DWEOp_n(O^58;Q|pV zO>teT3}Kc>&ug_>)wan~o4GGMTlxNP3APXzD##1paOaBn`Ym(ufx`l${Y-#_}%k4(}2!dRDXU%vk` zz}y^2GH}F^Bkby5TvCR zDZE5OqN-sLt|!6X7Y*14wPH?4)H{9pbRr}!b)CPe{_vv@F~lQC!H)OqC2#>Z5eH$` zH(y&;!^XtG;4W{gFjtb`qrS^3uozI-Z)F25Ub)5w^xfO`Xxq*)2}A5q0=Ps`Nk9!@ z|6SI3EAOuD*{w9tF22mdCUZ}{v!s-)d<>{Ebn|}(5yN+aL*;)hSn{Rm6~X?4KO5zDI6(9%e0Tenju%V^xx-XQAU zo#^t9J@X8^_{ytoO>vnWdE&|TFA|>o^>2T-{SP`AX(p?9y$5l=#K2-QMC!w~BcGZo z&uWZl^{myu67q6*$BL9fgVB)(Yp=^14oT!=3Ir$7Cvb)t_2s#6qlzyICusp?OV4BY)-aCaxkHV1e=p@H^!J z*SoQ;;JD`6*5`fXqoWJK07z45?%3dJK zbc;;v=A=UCSE@z!8Crx8Hn|=-I!54;!tw)yz>K~nkw{1Gio%Yg;!x7Jy5G%v^;>P* z>J_emwGr|&(ldGpakgsS(()mQz6uZbh#Tjcz!?Dc3qX=GjuO%gNZW7N&Oa-budunq zLI-O^-@VP{Xh=o3a&gMcl?@6`ke_S0t(#j$r*=dmLC=mg{;KtBY$>b9PsWb73Daj0 zOlOHl*!pv!6wgJV8@<*mc9A$DEs^KFWcpWKFuMTq1NzuSme9KzBiw_(o4vpT zDGnm)!M#q$(uY^2KGJv+v!HuKET#K@|NZyltM5RVRaRxett%Or46PNh2o;J7aEzvUcUZgvfr%P0_kt zTbnfXOZ%L3((7q^_$FdtnBA^GKrAlqBpFl&_ljA1{F!HLBIVEPYqykLu=QFJrbtU!rZKk zJR!=u=(0;!5C+&METc)pUvrmP>H`q8wR|P3FIN8&mFFNah}#NmXLHDwKn#V%_VQcL z2+OBxl?V3lDk8pTU&7B^bnXgfBxF8)!Xz6{nB0$9tuI=%&=!%ns0dDG{?ZkO>7J1Q zfoObMo+BR*@>M@^Zm!lGCg#LFg;_>gxN;1pd|KI~lCt}}T0|(eI30gB~&|pt0 zBf^r1tYdV@-M!r6yIS8-b8nK0N7nZ9=FLNrQs_i@;J|^t!mo-6P)n#i)vgy@a6!Cb zw37coeLw?i(>-DY5MxF&q5cKGykGg%z zfB*Ym!YiL-pMU}hVz)40;9wZ-g4kS(7aQdi5`HG@q2{0#3d(KJ z5~H=5izXrgSnkzznhpVb@1rp`|I05tie-lm9qn^GVAd6t+qJ*>jlJ^xiyj~gBMF`n zi=<74nmnjUx;ufs*QK!RS^aAcMHVlz{r2u-J-T@oD(A8elR=;LG{Fkm^zk2pwpW-wRHp_c^zZB%l_{s8+h3FY}oNX zu%F#{oBea-`}W?XX*Ol?N}CDsmpD=baXH^zz+TLN(9Eo5OKj528MbikYWrf&EPM8~ zm+h*Xe{Glk>RNjNH?EeQI@vY<_bUR!jEEC|wVMb}VwhNpirN^&k(jJ1qW@Uqg3I*w z*e1;A*fIQ8!*6L*>8S%kTq4#Y{u0S|=+MCi4<76vpth?FBE~u|hC%WE1>t!e>sn}Y zoe#uaWeWn4kA}7`ijFD25+(NGen|tg%2)jY6QFb2rm`9zJ9ezA0(4Dr0F)eP$dDm6 zfh?GdK*VBJue@FV<%ffECA`Swd$*j8mtX*MrdBU|6ynrF*44%_(EsA zGxIXsNcI)7C}uWmg2Vv3AXg4lZUp9ka5=7gsiyo6Q(xbsaiC4-7+YmTS!|3dbN_w& zSpnmRa8d{Qb)m-X#J_sYt^{GZT1cW6AP|u2q~+S@n2Wjvaet_$YyuQKMhSuxwXZc< zsKpWE^`6U0zb$sKD;&qv6TW$5P1aGNV-Vq~^zX&WH?|9I|SHiRg7 zC!c$P-A|a@SwtE`mf^%+t9xxC@|YVsYSG%!H!ya|X1C}wnp+VN)}J4^&qdR+4*%KD zer6LUOo$U8MTn~o#K`={TQ#{8q4Mvlxi620?pm0+lVMM2tdUI&>|(^D{)!k~##& zLN0^{k=0Jw|6~-{vu7`!U2iYG_>z~W&&=|G?fx_VN5ewjEfs<%*W${%Z@)wEpA{}8 z(v3ZlG|fV_h7}xhF#$zZh156Ynd0yIt`8&uP?S%B42q@D7_j#~mIISj%qsS1k_2s_ zJsx=IuU52XwVjG8ty%L%7(`|oLIArGhN_g@AldnKtO$cZ9Y=X#)IyY9887*ZYU&?N zo3O>cG3ugRYI}6)6unkn-USY!E89i}Ac@C^J|kgt$G)m|w@X`~G69n7kw{nDR;`5< zH?0fTg&5_tydKf0MC)<`1pCF21Z$h?^QeCn4|2Rpa0UPFQRUQ!wpD&(!4CwvpzaSmZJsKl{Q3%iIKJ~Y*X-t0e%{Otz?qO&T}z+xPCb zH_vC-tFOu34@OZdv?_Q&sR6_oh+%X}?hB-i{Sj`}Fp= zfTmS+ll8yojtDV<&Z{i445TH*B*e9aA2kf-dPP6&*=T~Xi z7M|N(_d(Ae2yS2q)E-qaYHDk(wk7@#*R_`iff$2CNE|OCMvU-?f?`m^b0YYSu;myx zZX8K@-mtH5w>#vJL*hk95+S0lasx9Em;{v}7dGv~H9g;_Zy)>QlTXOhTE`i~r=EJs zR8b$>_$liWX?K%jk=) z^rELy;%^CVfEo4bI|G$Ro8-|>O>iF;rbveo60;*BFdoBOVvE~VKl!P3L!#Dmj}9)K zyYs6I)h*kCPTuIeBK%|dblQxLUE-RW=ob_%Rz z0KT1e-R@F_MC)SQ*0X0%*UJUM7WKmi3$gOg1WA%K(Bvy!FE`(Ve2h7p!yIbgc8?IUR>fan zpmq%HEruW*hkfGbiWn>6UT8as^ks!F=2Ogpf&dA^I28exbU~7sXPxn-*r6lt zgX`?Q_uq@B42E7+2w@S*5+iWlx#v-F4bpTsOci6TyaAaY^Dn>r(q4P*b;~6|j^YC- zCWYTCjv!dqrGO0FV;-z6u>A%M^pMzU_ttIO`1~9{alGw=-dop-jH$m+nLMPiJ0v>l^u7j47Pvb)b-UoQuzdZbd`w@*K}uVBm` z#_6i{V@cRF`i5Fao)*}^04kGyPP$F7Y8jSmEh7aYZR&E<~?YVbC}0IS*6Jy*kz=20}!B+O%n|4hal}+T{4-kN3ba z>(LDhsv>ZHq4v*aTR`JW27sZ@8k0vsD{+DPQiL~L(_W%_5gA$ND^XA){Qmd9_tmwS z4)v4zTYY=ujW>FRKP4xUG%GM0iO+^(MXA&~^}M7!D_5*^sln5vWu7r(26f874&X)3 zDY9dDYU5t##KUT@jE8cQ6CGc)bcrp;4nW_eh>*>Z04!Rxgn<^-cRStZ`zip>Iip+Q zWb*uwh+2%j^4NFj*b#sAG<*B)w`~P+8{pq<#>^Skea{{?eDDGG#yfA?+O=y?B^KE5 zgAa0#h}JFISfhq{*zc^eTYh(|SwrG>fFC3UP`iXhL-Ks_uCGaH5z8IgWWRp>XcL!> zbf*@bcYRH^?~U|iEhJG3bOwnM)Gt38j+Y6m^syd-R>Yl^PI+u)l!m3g;;C=0jdvmE|eFZ(LOK-;hMYy zysQX}F~nT(=%bI=lEusXxT-(mVFjH#cXr8%r0R<=rrA1-9giMQE)F7G5Kc`#O+uE(j);Zw+-MJ}fn1rk2ci?&xmU!W8SZ-z z2Y{p@rfYXR7rma5OL82LN(LFmBsToX)i?4xD)yHwlkegFI4 zcg7-7lA!vCkvQ(SJ>q53TlBmjCsOq;UsNw2SCT}zbU=$-)s2Dp#DR`R+> zpuH0E2!hRl`azNaNpB>r8MyC2kNOw-XCsmE$141h)Ifc#d*tn*eO6{PeYJ==OEI4t z6&|YeLs9@S*QcL;It(KQqc9!M{_|Pt%F>vN0|yU5{JoJ`RJ}soDixK~Kb0)3tfa{5 zAgybTilu<|Ubl7~9pSXz=FgjNgNEz}a}cpV66JC2GNe0v>tWaiy#M}3mPy|!|H2+! z+t~@HoQhg9)5=g$Dt|{5BkbNJ#K!~@(y=tg_{6R&Xu) zb=e?{fIQ{D{rKaL+k+22X#EhINvGTdD`O#G5eKdCgwTVrniC8djzoeWcQ8e!)248= zg9Z(_du6_62x56#%>&`nAD?sh0a<*1hg#vcdA0qx?mG8DDTWJRo z=QrPc)9(t5m)rqEKW^o57t8A&jhW4X$`zBK{_|*+8ECg5{#yM@5+Il~aT4Qe;|hLr zWgR;FP#<^2kz)ID>J(eD0u zLoqupaltjW0nB|CSuVdIkAlK-pN?0AzWcp*-?kD|1fBc#wh<$SyNAV4)HmN{>k^p3~lGw`&K&9{K_S9puqH)E?-g6G7!fr1K|f_NBe4D^^JkJg-RTQ0tM!Hw7IwNKR*Bb z^ZiyaEg}dK-&RHVLxE8QzcE;h&Ijfo+*5fkeW#=Xid%onEw{L*gzk}@fs6uWXAs2G zTPv$_*}LO!8T|dQ!*A0nU2Uusv|{$E1E&y-M&o)*Af{2{M)ye? zBq(k8nkZR(!Clq{#EX3ykIou+q7wibgDTF<3vwHrI5i6J|Q^b zez=h6xg`EuuC|io0yT>wCaOQ$v}x`6K2{g3i>gYvHuRta+#BHU&-}x~A(s*u=(ID> zz!qnY9W>-XTe@JO9e4Eit!JC2cH#LyguLY;1t4gbnm}!#R&zX|#)!3xnm=qhT@!(Y zmqL?E640tebIXh}h>c(t4^M^9jrCM2RCV{MqsEZy^<$sx$jw*(Q6%IR$%y-f=ycyg zMJ*Gt);-$_jyR)JR$72o1R!bv6Cg3Z>-%C88&-oze;^Vj`EPE!)m09aM4;k6HsL_z z&M4x4FxmJ-5Cmc6FGfJ$usK4k^CH$Vb`)|JY-!c5`z1vXXr*)g_1C+^;j+sv1L4iJ z=bn4c_lg9!rE%4h7KL-UIXe|^_luy{V#@ZYlK~8D?(ow zCmI`-L46z;UtK$3$N^5!qG_Aqkrl=osICM+_sVue(gTV4Weh0Ldm1)|*_}Cygchu# zHBZEZ2O_r}Q_Tzh4*uv{RCkSe^Ef-InrDO*b@ftL6U+dJqEfRrQ#6LhP z033)nK({?Q+J_`y`X#B9|9t1&_UtpyB4L|uZ@m1PHEPo)8nqM6i+e<>O@zF(rBM4& z+wF!j@C?dGZ^O>*I|K=U%4@&fh3>)!H=SX-@a46yq6NZ)i8e-h9wPQUR`bnTwt!Mb zS3>S?BQ6^v?~|E(OPRE?(pM~i88c>DDSBBC`za$PAx_=DwN3AgO;ouIm9Y|#I^pY? z)9uS?Us)Que)&L?{T)s}({kE%uxYdB+P_|T)i&^cuRBF(HKxsr6A_Lf?o&@a)q}ot z>C(jsKsfK>VD1k@UC#yLuwcOgd+4EuTvso|EO$VyC=WaAFqa@mhc7X{Ac%>D*h0I6 zy@-g;OBx{EvP9V(J9hMQk`BmCEj+KXbZ=sPbgmYnEg=7Vfuv1J{Ttd=Z6*i=TgGB) zLuK$&+o~@lJy1*rLFgO*v6(;WXRYdWZ&jNflPW@nh=RdG2D|@%bo^lJQG&P|m^FKr zO8}g1i+0C0znJhxY61nr5lABS$U~3%F^AT>cVC-?*NLrM4Pzlm19Qp?;&5{X`qRnv z$E6p{2PJ({U(K35+j5EOr{mmQT-FKVl~=Ehoqz5*Uhzl%`UHl?bv424j$3cD*I$0a z_UzitKA1EGPn=Key8pY{PCw^|?hcqqmd_GY2(5Gl1@Il`rmvvHNu!@ zjr@0k>gZ@Ie``SE;k-)}R<5z>7(WT$rR5QJmkFGO5!YI51J3)=rOp%tg0JV?fDc3; zK!`>0`4y07b0B6w1V!H}7eB4mCH|Gf;Npufwo5L##9n#j6}NGaJC+i_JpTCOZYi!n zGurzAKT~=(?B**#H)GK!TXY-@F?&bz*=dt8OXcc>r5I4zhv&ms!Z4HK_e z3QLIUsKrIQc5R%ee}q;3f>|?d4Z(m8LJH8iT}z~A|F-*Y|D9ca?e%u)FR%5r$yHbX z!g8B8!B(Qw3cy!Ysvv7H@elo(4l@|R&LSfx*ZPr1LcAfcPb!QVP<$;UQ45TRC>2SJ z?V?E6t;K4mQ3W!s469eKVs#R=dJp>0%J=wht@Jk|mQ%K~s0DR&HK(=wv{^H>wD+VS ziuRY@rL%oJW~_~$I$5SaPV~cjgygjeL`3Dj7u>$WJz*aL$B0n;?svZ<5J`7C^w2}? zw%cxVD}Duf34}!i+C`R#8n333cr?ivFDuEFzIixiQtFOG;9(&>`8-Dar&LG_Pr@L(WH&g84$DXk-#!s*YFk5M;6yoX;efVxb z_@n)c3X=mdR8kdnZr_fOz^J0q()$q_xNY>FVe?hZAZos*ZlMo82_NJk)q zqX`9Ztq5hLqpXhvK>nw~_*DIM002M$Nkl2c>qP;@wL0uchO6s60p3WS&yyhVXw zZoc_u54IwAKoODv`VNVmCDD)(n(P3cc;X57BG9v90AyHp#1TihPG9?X-+k8!Q6L&s zao<9II{$}1{K4Z2$Y4$Hs_NcQm)(7@KIqu7qc=lX`HP^aoz-p<^=rK9n$q^FuR3+= zbial^!_|zVu)cD@zx}fJD}_VB*`k3!E804 zVI!hV5+h$Qla;Sl|AO`%+S{UKtL&TEa|rHQx7yzjeL6Y*s;zu(u|nd}R?Y0ryYC`i$NhFK>Af2>2hTqJ z1RHVW(L6xh50V8%++8?1zI&I|BE}3lJ|rq&-`;z9hU8*mN5haNy*pqc9^YkcR{Nrj zEuaoa=!CqLD_3R|FzK>n%mgNihuZ}4Nhc?yrEEWbB5`D)64B&-6;5cLZlxc5HWpD1gJ>UaG$ z*V^$Iv@H~vp|-ept2oMJCM|ANh*GuKy` z~G7Ova)M7%E4mW_*5z+RIik~Y#AMV?o_A-nUp%4)Xl9@pK zLpub6RYh+UgEnNykZ{QvLWKlYyH|$^P{hVjqel7o3Wexdy<1TqC1DEn(De=LH@M|~ zxL5lKE`1W~hj74&rZ9>3B_2zXB+&RNiMhYF?%c(?_U?mW+)Q0yj=>oalOnoltW<;H zPJGFCaV$InBUDak@xAu!Y%L(v1;kBQgORToC&^e=5CR$f0E~Zo>)fH8pPM#kp?&b_ zN0v>S3x8a5-L-b#BTv|2Ll3d8?ONH1M<4AfxHWhy-^U!vY}?8TK~@S76h~;9|H3`K zaUroI!ZDXq7W91@5B%4-VK9Qba7X2IF6yY#^2mP4j!)EGwU9(DpcQE`gQ^t$e<1i? zJ&8jh{thu>uH%x@VnlewwrJrz839DEC;rvss{+JW2mz$Al~Aq>{nilqFC9PXzWoQ_ zGPKl&G1*T!`$9YQ>@)4e(@(=ah=^&R2jvTINVs6gDWb%>HgVDH@?BD|rvY%gd zWgJN=Y;gchkXv95eo8PNA#~*>mv#SRtn6n(+(qR>=9X;DC+x-n70rSi0`Sh)hjzYsBV<6swKP#q8-ErUOW z{uSjaSXZ!d405eyoAx$GUN#&T6{}2*(i8%4Lh*(|Z>yC^XV#LvE|+#I;+%B;Vqs(l zpae%!2}nI~;DP%~_-7YgbTN?wH`tnjwRZdoCs^yo_3STyy2qaQ>tpuL`=8inpN+N; z-+A4Bee)eQ6O~+DvMc(+Ld~wy+nILp$q@8AhYyZ6~J~hY3(DG zTR_}$0wk_XWdjg_m<#c06<-y|Z7_f*2myzsmr*7>MhVXr2_e8#H162Zr3#CdF0=WF zKIbo7LUgn-i2nXWaF>xFMqH(s*(GJgyl)i@eHzAi{aIi{8IL>fyfeIp7l5E4!~rhH z74KI!-rz9@q;r*M_>Q~o^u$5Br!+Q^0+A2TCGO?rpiOlU!@xS-zgtXzR)ta*$n!ue zc_%n9HL;LAC=$mz4IA8gh-TAlLMEYV8@9Ge6wW$p75~Tz(zN{{&KlH4Ky_haO?!5{bM00K=y)Azr`u z`YTetVFx1>oL(X68uLbTDXBr+4V!F)BB(_4ja@o-a5caN78nch?XOGd?|BPg008y1 zqJYZw;ezwdv8AgEZ7d!)_36(X+Vrm5{$RKK`95ofyI=>@gkqli?l;he4C-g+6WUuk z@GK-niTEa|+h=E0j&TFJ^MFg8kf3yG-;uUt3|o2BI(uim=UXUeQw;enyrj0s>bHOp zTQ;L96CYjVu8x#~S!p2f9tS{(21aU zzx8EhzLqG2@|pi~%GcI=uYNWbxot0YI9esD^*O?_PgSE6Qc~9S&I&iNtli;QZ6yhS+F0AxK<<^t9CM7{E46{1A2Vi* zKNk9WOJ$54IWo>@h`6)^Ks z`$a%3ojZ53&zbLMo_V&<^e3MB8=nlLy=1u^KI~9y-yq+_=)dvSNLx`*V!yuj8haUa z+N7zo>|c*PZt18EWmlvS;?69kRD*46WkGVH{NNOU7{WYksJeFU92=vxHUQh&qPzY5 zLb5`d*>KY=cPh3A$S)1XKt@gutXza-MF@Shgl}(j(pBW^G%y3xP=d9uejyTHR`|uMx=GYTrB5|cxec9ic&Aat3?X^-@3f|G^Ya2Ic zXpb}bb1}#&g$O$^FI>IAZ@KpckZ4w$R`J?|cvV~N3(-yP*?mvD_10T4^lRy>eK7=y zQUM*8paKZbsjak$C}`7pg&cnR>8JgCcyHM2UP0ns&q*C3{c{MVqq6lAwNDAPyK|higoN04L2?CF(a3vlM`p$IDDLdnyJ-XSHufBG?k*y?Sz*k>= zWqo`0wr(9-+p{me=J^5CpBbnJ@A&;6?4Qp*Yt1@zwBx=%!tVU@L)Z#6A^YQ&*94^w=H8GdkG$og9PTCE;_^Z)Ff2VfM{*2hm8387aJq=b$Lih^C5y?39zp`X1yyU+UUV)t3F zAoh;EH&9VT5kwSG>0RkHBqaI%zq5OnO$?BP0E_H_$?WdT+_`h--qVXpxq?(&+R*Vd zRI^gUQ!AT9DlXL(>(t6G5%M1QSM9w2-usd|XS$l7BtS$2fNsMW#htyfp}0>-j)eP# zWHE7vk{`=C0uXG9Ep4^cR<3ei)8*Lvk)k8n^@`jZ|0nr~z!zrQave&bl14()Am zZl3)$Z;l9?A_c;N<%Ep@oO#l7L=*w3o}Xip#x_@`j<1Id)mqK8aS{NQXj~~W)_jYm z(hADSSmqWSZV@%!R{HELN%r}AxBDM@n6=AkW&b+(KznZBYcdC#9ky?8JMvVO5N_Md z&QhgLYuHGBAGwYvHi99l+%5|LR+qWR(RN{BLp9#Ha&J(%tp%J~xveH!TdNT$l-eA7 zHU!-vs>1W{*g&y|q8$)HCe9j^=gC^|_;t{#432`)CLsR#YNt?Y%<7wOW4-nB0-v7uQ?}7#Zd;MWT1hs_}wvavlxZ{rX zifN9#)jq@@k7=r?JvCr}VIruSB@gcK9MN8uw!>aLXz(D}@{hK2&N;^#D>ZRl*&s0w zpz?K%09t|QRTCHhCAaRuhf{V^R*FN}gkj)oU^hm#Z?X%Cn zwCUr<+1u~FZ=VeL)`q_ImSroGX}&ZL;2j`nAS2)S%NVZDapc{VLhg7de=zOip{$Hv zEZQpiJkqe%ms7GgS%jmN)roI5(LR?lB8k?;O|L&l-$4W5PmkmemJ%X#Q23FQoj!3X z?TH)IpL1o$)8s2Ym-Tvu;R>aKgZSr(ov+cZrCoP-U)$@@W9{RwhTAtkd~4U;e7jnR zT!}pts8%&%eG6{yW{rTg`8{qHLeQNr%*WM+poW| z`yc$D9|Q3Oi7s+->3>1?_&>k^efZ&r_L-Q0i4!NdMEE!DMk!5@bOs^>UzPt*`yIMznWh+qx8MS#TurUFlQ*K7yxzuSgWrgkf@CDUs3S@5kQT4J)FK~6t5rrv3v{`Xc2x0X z9zXx_yN)aQNh~&5Q*ebG+X|Hwg*^U}`j=&;TF1^?*)8|=ljpxP^Ge);GoHQ(+ac)z zVN#&}|4~kL0Q~Jz+2}#M)sz%v`i$xB!N0k3^~V!-V)l{z(E{8eTRwp1Ai@C1LtBzN zj)YVw%a&6TpGh0ccU%lth)7^+`0TS!?f2jGOmR@8#Z^Pdi4a7JnP47>WN?cxFWdu7 zi02egKk2lRb)+v={}6plf>aoofVP!@o22Q2{3fI%a}7$b!OByQ^3wX0F2 zsYlNqcF{!_#fU%0!+E?{%}l%GipzCFaJbc%^ zHu{G#Ht55T?8TQ}vfn1ovX5SV)lR+i-&SAQ@XkK}9J2=XZH2Tjh2pBfT#@&|3yI({ z{jzR{FA#tCN{sjinQ)F&inbJ+h{{OEQ|ee};$JJDiIPApWH`Ai$_g+qG@0b|TXVq7RWK#+Wb|q_vtN*yQ(LmbcsqJ8jUv;8=!f zfUqM71SSHAzj~(RVi65QFgw5;un|4rp^sW0G=la z6&rydfv@RmG&nE;0|pH6GSCehHjG7AK(GUGMDc3~qfCdp?XZmFEkvCS|A89Ss=J9};o?Ph$f1Y2tryRJj&<(1m0fb_ zrLokkFcBRjfpHB$8xR=IojPr*6A+jsh=(&xe%8uA5DIDzB%xv>5D0d+Zr!|^+?rYm zSphlkn{U2x<`1II#(Q(kmX49R@rWaiu-?6Ud)@$!2W>(8JxDE#V;`BLX-@8n-1%cdH-RAgZh49M<-xm3cjVjf1wWTEoV; zU(SV>UTlr!tHJm4Eh_Kg{mZeQ&t!X`9YK`iayLhSX(W9pr`Aj?Gf=g`L^eL8I zSEdl<3wZIFXBBO+%pSYvKKtn7kNhsTsi;>+AHa#fehlL* zyac|hDo5(*^jpslU9y9#{~mqf)t{6+x_(ChV&(){NRiJDnpnb+jtGSTqa7+#OuXur z*QxF*wl@{7Crh6#mULXBO>3K}^q*aJ>Z$}hH{12sUTkm36WdZUZ0fiPt`?;c;`@L9 z^$%|kFMbkvM823ZeSPb;cO-8BMgR}*Hj?_0%-gkZ@4sX33lJg!kl1kk1A%|{-7vKf zk>EKGsc__|A8o4+TRMUG1?KA5V~<_ksj*{R1LN@JmtXq($0i?$JMV+z zc=hkK*IuqA^2(RG8q-Zl2=A2plc$02p-(UcB_T~}-D|Ir)0(J1=A^X+?y;GO1Zjf9rz+}U&3Ia9@l?}mM6Rpem%vly$r57^(T)~~BIR%pLVL!cL; z1&6;;s@>i9PSpW1d+LSfEJIBH?74F+y>?x@^t`j|f{U+G)zE5o#ibY6jdwm^%N6o@ z`<;EAC|<0}foWSbmKh*LbwtM(OemqP%a@k7iS>DYk^xwsqg}>(RhJV9c5c*ZF8w3Q zu#mMFv6Z{}OcT4PaJi++xo6iMcW`1jRHaO-D4%z2akj(09%8%n>LKZRmOat$E<5Lv zOKr(C*)eC$uq|7*Fu4OnK#qfWUq{sTvdy_7qf9)5Xjldk)CXn zJ$gkP0e}0=x$X}>{nYk3@NiqCRGvS4^_d-h*x|NBQg)ua`6WtArPtkR%SOulgpiIH zIovX(9!tgUu8E8kkH_#Bh2#MsLAdOHqNO3J&wsbWyld!5XlN}~=!1ppa1V(}14p$|z;op641Esw!+4%E+XP>3g+LsC!m|b_%jW%=6U+!yzW1ySW zSm#ptKP2M6SbWxTC!J{NG7nHEAVr#)|BC5);o0Zyw^7stc~6Og-mve6eq%fCyN_LX z!C7{^7`-Cl6YTKI2{VRQ6JwF7ce_qO#6N|iCpaCdKva+l0uN_o*JAbrDRY*xR4BWb+$gIX72|Dz;C+H16VBb8#E=*~%8 zT1^tfqpC9Y;)^fZwq3XL#4`Q+KWS9)Bl!^%mv+kn5FvaSl2EY`06_+z)&gpLh{LKJ z@xr<6nM+gyB%G9RJ~rCJP8vcsX)l-t;)y@kljmafA&8oPnzXdpT4t}tn{Uo#F%#F? z(rI6TN-ngS+WmdP1Q9Wrp137YY&}MPO0>U7++j=$L;y3y72)kObm+J40O*sH~dpp^o0ClKo-oubloRkN)jDzDz0dr^=CVlMzt? zl+L;S?aB@FLy`g5Fyp@3yXI-a6_Z#40)~qY5GJPFcr)c)yJhQEK8atDO0{dJjy7KD zJsWM&!ty6hwVGMgr7ci)zU5lX+7OMJ$_`JIHj{L+GJyrPsyhJ+v4K$IL+FsQww3ho ztI~v`h9_jGR8YT2=7Wu}sumVud-w|wIe_EfxC!HJo(Mv95%`Zj`Pe0YBz_VLz4FQ{ zDo`@rnBLTy)o49w(1l&Dd1K=l>@+a7ykyvp`OG3p)ATR-#ZH`vm zhwyz(t#KYE!*T`?9$6Gw_FJZXbn?@ z3*LI|b^Bq&PxkhUFIfL4pHwliMb=kgz-e;g9q`Q4_Qkh9*gJ0ww5oM$OB*By4UW({S+5VQ06v(G48v94v1M%|sOb#4U##*i$iLXgtF z&Xd;4O`YrB&QZbsa#_Wnb}eq2ymZwg03n9t)fKl4tdutV>&l7jU*&8CS6i)yU3K9_ zh6QWu=8f#*H(ryvFW+(}O;w%%y<#CnN(QEq!l>9Vml#q6MBv(4B!IB`PIC$_EKCy80!gqku#w7QF z5%9KjPml_q(JW9pllbi~zW5@hap>NCw@7$lSh(CrpYcs-udu=!ufM_1Wdg5$i;8Qy z?#l1SLC4XcsAfchj7~?oSjAgiV*PH84ku zBu2Ms-9f}qGfkg~sdp__Dbs(gZ&=w4Xe?MaB&k6~{im21@XMGnzxuj~xYR~&T1|q& zwX)*_6DLn|W}S#0vT)W^8st2Z2DNQxCmyoD93q$4t#b5h*t(s}K?^1EwzVS8iORT3m*3b^6wYh8u@zyCdC zKYaOxa^KgIiD0%p-0v}~C10XGO5=TuLWEni*uu^@^9&LFRJ&I>AKGo%-j0+bX{vGw zI1>O?sod8U9;5gk+y@gN!1M&{v-_SZfvy@VxkYxH93L&adPLar{zT686U+2R=ST5t zD)$loY#=5m+DZ#G!IqFv-X~4ShuEk)#e`eA2r!;c!K!`n>8-Qb|_Cc~F>)CbJUG0rGqFNVS6MR3o2EPFOTmk`tN#Hn)KuGjc zT6DnQd&neAwU4E~#`C|j0c{0<4*<;MGIHXJ$yh<;0t+Y6f#E3uOZ9Ft*BfdtiCFU-gxEZ@+U~K17*6))woa` z4Ew=@N-Q?;l{akKZ@=05AAM+K6nvL#oMHeU?$^)0{&s}*fA|qgZ`#;aXlM%Xfvg}g>p5!&Q6Yw^g3%l*>L$rV1=Zk9~UW&>DaNqim)rHe^q)+rW7_v zNzxEm_vleB?-h%eS(bbP+?c1u<)_hy=uAu%;e`9g{VlG7pKKe~79Sxa7&{Jz=|2t@IL z2OjX`KroFE^~GZ1f-N5h!7%Pf{DHCLT0V1(4e6gb&W5@ljS)aQWrGyY9nrpByRw~L zfwSmueWlVKF?y7Z9Q~7}h>1-Xv!hN|ptTKf3Cl>r1Liiy7cCsjJP;xJ{!xpc=P5Ew zJUOk~*nAoL-&VYQdb1W*DAoO9txs|>6wRJveN=5TN6yC!l|1OO|0vd98j%GmrF_6q z$JlQ2720Qyy{vIgOE2wx{PCyQ$RXcYYx$2{cE!bBdt}j!nU+zjx@wfjv?Fh3U%Qdp z(}mJ;OSGF6-GTQo-xLY2Zq}fo9e&7Rj>aZVn`2)N{n}EL@1a1r)H4UGFJaD>`+gd0 zoFaLQD8zjXKPARK;NrySO|lmt#Eh!qzR7?m?{ zm;bx|sF${C{txbDXPTE1!`q)7{atH<)_oL$+8HGERr zFc?0L!gu&fMGRiWuVYTfZ^e(U|8IKKBqY)ZXmX@1mj`b38nS^)EgFN8>i^gQeTWik zXF1~+i+(2zh%E-RsdG|95FzGGL_ixfsHtKrzu8w`e5J_=QjRRZnKNd@2sAeNmMwDJ zUcXhRt+bNVNGTFJ_h~C>48k8&j7x+-&;$_L*Fa1Mt+NQQ{j+BhMx;SW7ecDk2jJeN z`WSEnK({A5U`SL%J7s}iei`GZrRmuNBT<&?lIN5@0*qllsdj;2>*rk@FA4FTci!s>@r%LzUyz|v%J@25aQ=n9|58c0 zUQ) z`0@7DmtQKcz%qM8*#w0I?5Ss;vtOqDY1jSdDy!OLbIZd-mz61ou=rTU9H6~tYw<_8 z0(=2*2gNOTUW2XLcd(k0m#SCKupfV&Xiq-(jN(q4+H&;=GuE2srnly{e{b6VxD%j+ zFZ^4IKh4T>66w>%(8oj?uXWxRCLQRGJo(OEukMb}yj5*@ugViPsIx*dMS-)`LQa>X z-ZtBGQnfYWv)j3ioOU6Y11||_xHWp#hwo!nWH&C z`o~6?twq(mMGOCp=d30|&mIH|Q^37J@@NA-`}}hiH;nVj^%f(4IA0e^B`L{7l4l?g zf#HZd^=}`^Jm`#z#;vSO!`~W7{tz1hRKmpe;}ZbVeilc<1bIkc8Q(b4O1AMCjk@c;r}z%lQEYgt@s)&y_9zhDp<> zx@Hc$cah8-8!L2@^n3EDeeB(L-&IbJlcSHJbrpq%O&Z%y^7TP4cgvl3!=WopxYnx> z3aNuvDC6A^(n5GHhMI-bnDgbC_Z7Nt1uk0o#w&1f z@{-CQ0U^57TG?4%A&*p*4y9qX*z8(;A5crNMF6|2Oaq1T#^=qe-EBK|wi#2V`Z<#( zO^(E|iil^(lz>MzQaT>}Y)IT7VH^YL;CS@0$4CgNVxuRHw>RH1coJ6B%+)LZUV1G0WD>a+{14b-g{UelZ6(FEPt7V6gfg}yKPsG(VM+s zu@xwb-^2X}SZclc?vLVWg3EbB#+FDbGypIgi4N;%$t3z?CvN{l3|$vT3EL&&vg1qi z7V9-QwhUXER8)$Ljw~$gV6uzE-KLTrbLnE+S$4qsS=ly01%iUdc0~2A6vL|9js%ZK zKj~0Gz*U7nu%8DcU#w4j5hn0+)H#Sh#2LpwClvZVPBzrVdM?2I03gO%G%nTaw^ZGa z?|58abM@6y@k_m{bwvC>gdZCvzhTFRxHQv-DFaXckZ#x;U&WtE6DQeBjqNJ?zl!UU zKd*WOkdk5I+O%n-tdeiqZOX6~-X{_~egY6|2>Hm7Bi&Dc^PTZSn-c}D;k^)M2=lr7 z?z=~lL5bLs$&pgP+bJ8}=h6;wAI}vKy*!PIZ|eYHfE`4Ps%K={qB)woxdoyfy0Mby zY>WW&H9?FFYm-7*InA3Ye*Xl^m8p)+*M<)j97#IfV8dhL3V>p{mQ)cm2j()N)&6sck$B4Mqi zos&qvtz3PH)T>RqFW*AUCd;F?>~YYm7_h(~u+pR8xv^RLATJU2RyjG=v2|N<@--bH z`)P3Af@zB7P7y%{=4k=XQ8v9(wb(Hc5C#|$>i7xKKm0}-P$m}1e_$X81EhvPW?UZs z;QSYVEx(Z*#>13!-Pk{VS4iOmKLu&snE`#{{@jNQag#JoAZa28$^!X1cf^Ph5du{~ z+)|eNY^vwrq<6Wp#F6^)W@lJ8qI^fbcZ3Iqs}HK#QR*H}DPlmuo{D~(xqwvkQ!|X5l&t%I}9AbCnjD1wnG5HNgt?sa301QlUj8k9+P>k`CS5 z~uqXoCRW1<8T91}y@~gU}k0uK_8QIsj-5UY6wet7=eSQs6w8hTt2puE#Vm zmN1-XCVu&KjI!xXw{&I5i`36p*F9Lv_L<}H^IYRid2JLJKgtOZ*zbS?T;p=5h`8qn zfqmDSgJGjWCm9+?{ys*8@dZ`$l4PuP=nQ~RLV<{Np_qv*nFks)P)c33_q@`P({{F! z;gDVM{kPw-X9vDvuRQp$H5Re`&n5r1Yi_&UK7Qp@Yt^-z-F(Xpc1oYK?PtB?YHEME zn0?ZOMSP%G)A1WUUQ5vYK~stUN{yOzY`2|u^dYJtJl9_JPlk^gX|tzHRi!}TJs&&n zUpB~A#zYN{=4rYDv&trvl&$4;b5_}(Y~9>H*=mUq(4x!E)4V}aUAiQaM%pJ~{30%K zO?kft>D#3*N%c4ZGGU1ge(kk^n!gbwzUxlAx+I1=9l|>l(_wR4{A}B~DE}2BS;nzVJ08*6#Af?hk z>_hAyW&$(-Ab<$6EA5KpZxtB<<`WwPzCZ*MMxc|*N8_xAf53+yeyB9jgI#@3orfKE z*uh{9Fg@WXKjco?!%Ne_ca_sU&Gsnl+F* zeB9J2HhKCqw;!j;SEm?pUDutdjP^BVb;R@|V2__L-ro}@J>J1MnFU^c`6ValtPdEo znqqX)WE;;&&$N#Qe{OjSAI#8mQ`Codoi1%ikrI*B5aDauw3+u1viHt=AJ{_S7Bo5C zRM+E}gATU;JMUaut{eiF%0#q>i0;ve@lTp2z@(!SR zTu0;y!Ymw>MiK;R0d`cjO1zp#1w3D7ftj=ZvPb(rX&EH*DTn%>hlep;F5jd^N*q;B zzD$V@>u7`%{jn3ff6%yPvLUg+Qln~fK09bpYGtn6%KIp;DvuCK5NYm`g|@T2eQE#u z?}ppkZ@=xxuBtqK7cE_AyXaVO=;Ky7IW6=z3Z>9nqy{ty-IOCf*yIVB!nrTxdJhSB zkgkG+#U3pKCIiTIP@$m_I8gTEpalpBce=93J@d>nZvXdO@H&9>SQ2O}9zf`uOOhkP zAgDUyk0(D@d<2+JY(8(ru)zp0A3_S?-o1Of`hM@d_x5-9wX#pb92_7C^xSjLRqptk z6qT}#b?eqG)(P5*&3*kE?-LU=39*yc*$1sR&2=4VKQGZF~3ZW$jzG z^aiIX{J5$d8^?-*A1{gNykb_G$&w?SlCW+)25Dy)ErXb?&l_O;%wbV0nJ7h<0_) zZRN0=1t9P@-+XgSB@aV@JrUcZGYC?>IpWZwL3$5N0K_^t4hFkENdCi*Ke8i~Lp)Rp zt{+Yt{$$jOIKwt{OzM^*sj6lhKMcXUi zb&-jlDq?`-`^C^9(g4U;K@2DM@Pvo>bt;d0)=3pP+pQ2$uTn)Jaay0epS$nA+t<#E z&p+$Lk>_F!oqzs$&PHd*Q$JTW^b~3L@^nq4u7@0RrB%p~uS8=d_5sqxP~aUwWzrwM z8Rl(DU1M)48sJ;`61+O#DNC2x@vAStvayq=ShpRNaa8$1UVrm#d+^bx>>Fu-YUZ@i zy(APsT!C^*;*pD1{}%;7x-?3)nr>kS?7f%w8UL%fi{{%z2^jCF^tdT^Net)d`PT%_ ztcn4cGiSCfQlv$qLy`eVz&AuvKkT7Xr$&e|i?h-p+9qDBaID0})~s3G>dFS^DS4%0 zRbZWGc?4S&bNj->)Fi7LY`X;U#$r^(1(w~St1b(ih0Hk^n0iouH&_j%uD*hL# z94!OL2I3tiCBG4YK<~ph}LKOJuqmLYEF*dYcO)=VAZ6yaS0Va%90SkPN zLJ%@wgE`01m+$-Sx4#{8 z%+a35p0&zxR#F!+3^i-3;E&E7Bgb5x-GO0|06`scGyoY|_b^CH!Tw(hhc!bTL ztDGY;RTQ(q$1?$-#I;6?!Zr4 zpo41w$JN4ZBt6S41H-U}=GOV)Rb$F^e(U57ijP1kY98T+&$U z319q>vQbXVHhjvcmi z<_IPtl<-7_*`r4fXEL}?Fk6HP9`@9ZuUn^%Cw1{>@RpN*k|VIX5nvH=yvVlRwu`H( z`Borj-Hi>1%)$AMh`2Go{36=TN)!%Amvk$Je8AJsTF>6S-NyoR3&KcsX(P9dnq`KM z_yI26*CtNHD>MdZ6H?U90x|ih@xfuNH;Hs3^3+py{l71@OI40|yDpt15@QuA|0EA;m1-wKI zQ=&us(y)z(+hF1sER|Fd`z-(Y^?matw;-##2($d zbh8$6Tp>Jb(2%dx2bFa#(qfjR-$Dsc0zlZc!ejjnzsL5`V=ST*6hZ_Wfm9DMr-%^k z2MHZyvL3@lvzaH0xRJdmfrMZ^oZ0HxiZR9RY!ez$--fMDWcrrS@gz{GVd?RS!tH7$#f3 z%6yZ6i?v2HK`Ii8q}{eTtz^k(v(LR~RkBj; zgwsyd2^n^%974}M?KHbbISGb+`k8$u)4<&Mi|ne)F1O5_7B)u-hl+$NLcI_*TX~>9 zWitjEm%V%UavD#LgJvz7Sx(y=du`Asw&>3pR!~)@5-~_?0>{(BF{CxFqp-(B2i{Q< z5@-YnxkLF5Nnf}CHMN{!w7w#$u(*!0KH1h1P`EFfJKuVW18%NFA2{}m{OL!_(!Vr$ z_#!P}&u^gYSg7KO=?9#EmUe&oDwQB`_+f`T65un$JYS5)EUDB0By?&H&@Q&rm*mlZ z%{5p1_gS-M%0H*bYRYMd62fQK4Q|qd;)_I zAUGIuJvK`+5<0gYPDt*PBe13s(A?g7o2|7ZwI*dtFIGu!P1kPF<15j8zOs3?Y}LxP zR66hNJvB3n7{V{m+K71GMZWTLb$R@w1!&g1neT@U|Ix;c8}FroVc>l%q{#zMHK<+J zYD-|Lp;WryEU-YHRP4Cs4jS^cY5+WAX|-!A9e8tl@4ff5ePUOge?F=}yY=?l?f(=N zu+KjG+s}#wnK5&Q-S_0v_V|PMS%VI3ZBd?51#4}`d;y|ej`pE6rn!pqO} zw=1u`(SBB%;+id5*a~r6ZVsSnwzw|qTgAZJNVny}KRF#b+Egi4lK=of07*naRJmuI z;UR&el*a&^RI65|-FyFiR-|Xmq*5R^<$+cQ!g-#ie0Ap}$gx$kG6~YbO|2X5SuEmO z+KX8i5^K6t3plH!W@g(iBE%V5?Ng-Y8~pj8*wB-C?>MCe#YR6`_0aJHpqgGWX(4*H ztJ>f%bFyC{reM;fiN0Vy_~3mz>&!D%W4@cx!0zF`0ZWyd z6vhF-7XZ~iV}pa?x8Du3C8{A0!{ow2;wSJ!bM z3CR&y%?QNkj1YenIlzq?{fGTNVS=TLh`MjiYOYPRLmoP*^-IE<5AbpqxEYWSQiI1f zzDEHKz@bXWlqTHJrcFC*BqnG@!E(*gtu$_e!!Tw zSPXx!efPKTjW6n2F|{#arljPfAu@zG{AF-%$;W^A9sSOLb1Yx3mhk5mK^l$ zPxhuX7U}is+6tXs%&JnNb$5~$KAj_hWX&-HB`)3oUn5Vy0dAbUWn=_Oz5q$H85wdo zL6NjX)wVjD0u-UPlC5uNF#ro@&$T=yAR746E8_4Y8VF+M z+qQ3S^_1BQ?mm-6FI?da37mNR7LZ7^M`RL%7(?ulH6 z9(cgdIqBq+tw;AB?i&E}0U-UuWZ=Any79sbFN~@3xko_O!G8die{cxIdwbr(1-89> z1kfBLAvpqT8Ubb<8}o_{;@7BYJ)8cQ2-cb;L7ksy00U5{5MRt-vqXfaj2|D-=CN)| z6+85pdT>gVRLRJa_H4RW;Y=5iBaBcsIkhM9F6Nv!L{aoLquSnFm@#%zid|JDkb8Xh{YW=6Rud(E zUI~({YNnhTb#ForDcM0{#-1)B+K>W%)`lqNyDL zE!3cHUl$qxZUS*Fka~Sfh1vb7MYx&rU`J{ZM5_L!EAa=}!fui;02BQAXP@=Hm8CyO z?>i|I7z7{l1{whF$1?@3K;%Iqf3fQWAAkCZXC2GKPUk@CM@kI9IOk^p}2&8#hi~zEzCKgd`+KpgbdhbL;*G9;lr0x#C`x zuy!M30`RS24Tl^fOSSHa0KjjDd;p~Z>jn)Vj(_;h5aUieF8ymgyVg$&koC7zsl)?B zlX-2Wg+58YT?WxadLH!M4|duqr>ZE_Jj;?6ac2_|LIQ!-0F11cuZE4N5z-r4;2mAa?MO7EKHPKPy>{AZeeC=1zq6Uj z(nX$lBz^jQvYdu)QuQ%33$z&8^~R%rAow`s05BaeAv^D~vuuvJZcd1vmfR&rp!5-l zGUgoQBLshj!q>i#pNaC{mVQlw|B8=Jg9i1SX`bnMH6jkV!PHi=`>6g~wQA))Hd`xG zV@+w^&=xFTN;z*817baEqttk|k|nii+s1PXMDT;eVW@tQ_0@I-G!}T`^*8MQE;!fz zoHoO1H`vUE4*Ak1%=%LazmBxUQlB@Jv_EXnAbaP{ckJqmF0o-sCEoYG2W`-YA6T6& z+j~Nym{VS)$%_Bw#j0QF^i2^ChaP;O{2Zk55H6xfQo9ZvJe={;%f-X!`CynR`74fT zdEd(hY?_cT>bn4vM)rlNiEIa>`Pd#PtY4MXdh)Fwh z)+`$=$pNVYqQ0t$4Dm-@8IHp&9C7#&9_I`*lZ505lxGAoQ?jf^b`2Xhagxk)(jp1j zyA;Yk5h3(1zHeIa?!`s=TET+~rG;QqVsvIib}!k&BnMSJt@fp*A=r`h1QYhL1Cb9-WOY3ueyAOZ<*g?tyhbuJ0Pd6&Io1E-6EI4P?AT+D@zSr@@8dW6 z1)>SkN_8O|v;kop!-U4vz}B>BQ_ua6rU9)+lO~O=XRn?@TA;rqBu8KkBY*)s3QTcy zR$V%GwYh)Ix7;}kElotolhrsO31`M#P~xZc`c-{GW8r3sX#XNRwxc(eKq zeEsCh%RR!$6z?IKLJ8j+AvHWrbZF8-GVKz}D$@E{q-%s4e2q&$pg>ckh|?6EsagVC-+dSqpu~Igr@?Py?W< z)N3G%0Q}BBJpW1cTf2@NhXmfA=t+bvf@lER3)e&Jn>B0hW{WXOK*V@bp^H$%Y_+va zS_QA^9&IPNOO8NUN1$%4x;B2=U#goi-5K;^kpOEXKxMs4<)7zy3q+`8%(q4&{79%c z_yVl+(g4~xM=|nQBCw5X)UeH|aEJPv&;Z&(a|q#;V-UH zPFTWFA?-Z!*rRsd1?Q`Z-ZDG>%ropx5&SzJ_@AAt&$5HsnaUP;$RP*XWtU&A?MiFf zvV|QXr@(BLi!Pvp%axIEv2v!AbkARjN_3}H0O!QclV6hXVV+D7J$BsLI<;;Qy(rZN z%jAPl_T0+@m5zLd7lXo7yOKSOoa%lL8iQZQ{Ay8sia3JAh1eTO+%9ffJ&O`~pOR$F zTcU&`sj@}64}dt!N(bEup&&)rAs??^eL*EyQ$!LDc=V5>6ltSrqR+mtS=_99A(65I z4tK!LyY3=Qz_lLZk1hXnW&a|<2*@Wx#2ZzAd4T@l2pG}<2hV@n@NhvL|K^)-oG~EG z2j@Sk&C&m=lH4*vPV@5IG6!p1!jKt|^RE>Wx$=rDJsA(0fP+-(m(apMypi|;_DJ*m zLsBOx$NYKoi`@=$0oNhzhb11a&lZ87FmZyX4(6PH9sMt5FUu05lleeMk1(htBuAjU zBS7`M?Y7&_I;gTGJ}ny?kc|_+n5AO2=PCKlVhI=#DZcb4dGqzxZN`+T)_n6OcEa%| zNbSE!&hH|FXbj}B4_@;1tv#APQhwJ~;h?bA)T%h{U=A;Kk6)t421BFKa^7)gUpwRM zvmD>t(|>@f5T0uTUVO>UIsJ60_o~^WugEv3Q%5`bC?Rtm?BycX+Jd1fPQjZ?q3q{Pr#cA*tJcwOHT03RBp^{*6g`9amr-G*_9z{ znvBGoI-T?hUrFO6!j31ejP$m{c3rI~SDE<4;ZD&+cVMB2(4q~9+0Vr^tO-aM6f_8& z3$yXx8*jAz_utP${XYEgLpKL_A`Tr_4_sZ(-kAU)7S#6udpwQ_17w3aU;=X<=L2X^ zPCV{-&tAy6I2w{K;E5;tM@~>v^eKbLfHikNa!vAYas=W>Ky!z@_GpxlLOy@^`*5wOHn}mpL{|;t+0dl+{=mE z3QUsN+o5)1h7bze3ZS(}+U{{<$60$N3);MKW7opzVn}Pui77DkXzyI3n3~d4C}B{Z zGzm+k%76Zam+Y}eAGdsk2>$n;`|OH;Uu=(x3AjQfiN&?p=U)%C>C0xv8oIvkBwJD>GR&C+4W%0381)9gG&FjIUD_40hq!#Jy7kVCm%WMgd#2_) zc7L`&^oUPKQb(N)fm$e)dmv2i?<2xVR1MoVlCFsos3oT1>Wlwvg)-ZrSa&v^5I9J? z7@R61{0J!v=P&T}_Pfge&X_vGQ;dsG5CXI9w5=LaQ}&h_VG(Wx`5N1QUvjZ^@72>r zE0peF<=wqo4p{YVIfDO2ybnjAG=uOqi}WmwWu81=Oh&!hQ8T`NPphJwDZ1{%&pwkW1R@_9 zFE^ve%vdB2Az%0sEsJBaB4toYV2EJb1n%G_+O?tKxv^o(11_Snj+ZpT36-#C!n1)W za&e~7N<8eqgXO-OqGUWT8?pER-2U2vBO5JJOasG&K>zRm{?F}@v**q!)e&i{j$7F^ zG8n zbv08{b20`@==krk0~PoXZ7Wr{3`tzr&3bp=#a?**RZj*qUJ^R$EhP7~1tfaZ^duG{ zljp;a^m8x%NBZ@1sUsxwLE@h^`!B`d=Gt}FUFVtqKw8t~fs0Q7YX1P7OOYWq7BC5i zK-3pqaDknE#{cB7s;m2+K5QOdWI-YLB&4wyYH;GBOa;8-RoFX{@q6G-g zD*b)FQio?`Rq-%iB6(W2%(1MjY^^~N&Io^07EFatz)qs2gLCupx^n@SUVYO|2L5^Y z*{3}rPxqd^tgRS;_uqft{uuR>we8%=a+)-;0dKuwJMOf-opk2e%AzveqX!BU+E{KP zENA32`3z-Ot!~RDlys8AXM=iKHhu0&Eoi<3q~a193+beVT1Z$l)b3UWLPu13 zu6RF$*uDROAEG`aF5$s!1#k^WRD(piQohF@59hHj?KtQ1JNxjN??7lLT<11rKk`rb zQyPj)vD%Fq+a#ECNzFWOP@^aM6KBG8v(C|CNR2;7seO5WMCyBHJw3qNZ@+D~-Eynd z)US^y4YyIjQ}*{|ix);5-H@tbc%t|Rvw|A&Vp}tmS&-ymH54)!1svxmgfFG;)gStV zJOzogU>3ejh(iW363ynjq>Xy^IsXGkK(xU!m$k&?n zaVJ*Fjk#fj893pj6YcZQKespEc+>hyZC_PVJc)b&9R85tSNPWh=zd> zR1tH42JRH4*e1{YK}yWis(lA5nm*MNg=NU;F9sppt^`qK{t;q}4Lth(34{A7c3p`N z5Pcx*`7BwdyLNBD1h9c3h7233`2QS**VV9JM*nObl%BV7o0if{uCR|@eZ!*}GE_yd z&$(yWA0xlB?9Df`6!jMd0=!TRKsnmDXY^y_{+t#zT?j7B)U$NirW59Vje*WjNtJrR zmST257jlrIi~dw}QkAC7Y?0EbgO!#j(GuE9G$w)}{7F`Ic`|rLRBi5DP2UfTi6lQ^a_TASmlEcxj;`BfJ z^fSBd=38v{J@)Whk|$uqh!Hk@=1gDMNd4Pw)5Ui0-P`)!afeNmmf-d~`da5ML>>t? z0-J24qm}m;#Dhc^hLM*4%ju+zdd1A=fRe0+)h6G3=PwKt1AD84EbwKo-|da6(t&rgaR(tbHtntOMd1)8xqz%McI%~ zw{hRwnKM`Eikl`SXT}QWW`>IWuJk{=3HNOAeB6Z-p z0;DJX4xfwlz`0QZ5Ptf{>ZF8)MLAR%sAe?gL*E4w+GBm@a(28(1#FxyPqtm0Rf>Dy;jGE=w9%Pagw97HGB z*1zPP-$|x`M<01a;ejuxNKua6DdvB|U}TXM>!gkR{<~}Yl=8%%Dq7-LX&m2r z^G(M^&04mKsBd+GK(>Lzg(L%zxbJ2GT|?^1RfVcdNos}4mz`Rqr4T=9A#xQ37OytA z@s*%JALRnTDp(~u)pE9IYF~Z#y;N~2_Ri~X+5v|i?5D=F^kMO@Y@-~X!oAhL!z!NV zq*G2Qy-}{$wL$V+#pR`6n}EMUa4~rxnIl!R=Qjv81T~(phG*uyIYPW>Oy2+CeK~H< zv>#PZAwHFJAmk;bcQPZQvLzg|Q>RW=SE*jVAO5|hxD{Rj4vhfEtI0X^*I$3N*|TTc zym|9nV-SXqeq<>J`VK1S^4MdK8R?lrU&A?JUy>;Z&k&9$>ORbI#*udd6SP>8G-KRM zDR3o1i)#*(nWuUU8=o?U$Y`Bqa4=!7E< zw$5F<*m4y-%F?;w5@XMRk4+5tsJZH(IY54axpU{qPXC+7;rqLdFaU%Bz85*MY=1+y z^YROqsOfGR-W#NXzZ~30l)&j{oM}V8_|hJF^fB9J>n?WKF-I$uz^rY{E$ol+Q|*U8 zCfO~^v0iP({2gT$H;oK}0Jvu^BQ9u5ChpYW{ z^f;Y-v9`}rGSYjmSdnL+3>j+u9`A2wXbe9Y{8em}WPT{_1gM882H`=A{kZtC2+u4b|a#scnLC_#=wxpud* zbN%@1Z#G)U|AZ4xuz6Amaz5@~ToQVqkBJ8xcyU!^K%78F2Q{7vpe-b;pMU<@W+)P3 zsH&!Y{q@%_+0Rk#@*u$nf?8dvoO|}{>8X!fwrpv9Kkm5W{#Ja6b|Gq97p~>E0P%zz z?Ljs%-vYuz>Bq+(f9!oglkmkCU$|xfZNS}k-)(#CwU@UEgOZ{NR+9M$_t=>B;Tcf- z&sP>b7$UOb`8aI^4^oJ9uH-h=#M~3l&{mcEFmCVNdoTN0NqqL*XjS>q#nCv80Grqy*I~-#}>@FINLs$lYL|v<@%G z3%@138t~k69u4rE_EV=#RaVgh?5p7;#kA-GA*okC8e|=AyUnh;@n&20`#6O)a}}Eo zf*bzUtLQNua?m+hI882GV%@gc)=x*rqpLgn@f16*pdeobPExj$o3>r345x#Jd}ANH z|AG4gq@|=PT&b`knvcl+*Tdf=1F#+jxq`R&jq5VRvDa4RsUmULj(pGnR3e}OU}h5n z=uoJ|46@e00;veAHL7KuJ9e@$vdNRS7vNMjmP-;Ue+00}lc)tivWM8?Ao+;Yo-hFr z8|DK0oSYonb=O^OYpF$%(ox6bAVm@-7>IZX*T(+_(GNt8-!VA_N5c5?_>8(gz?o;B z=^y|5-~W1A*?tP+gdutDwb$HdV88wLvv=h;vit74`?Jt4M6)y|Bec0O?J;+>mWgVS zvSpG4W~oAFt0@r-pA#PRE>=kDS3XReHf5^abk()?m6*52HLBV@cib-SUa7K|ER@~5 z3>-B6B;XKf6mnX$u)TWk>GR3W0GgwYD8k=z3=B=i-`zhK*)ZkV*;1`OtHVd6iE){( zD28708#-0B0|rV3f91hCtGJM>%oYRFff{S3((LXU(``qoyhTG_rrc21JT7ZyENb)sQJ+Z1jd8&;!O~k1n@%%Ohssu_R$JlbkRk2;e{8v zj{y?dRaaeQ#~gEvy`u_{UAuO5qJWP9Ou)trVN4iH?8-kXAfC=Jyec#U2v(^7`7Jt5 z`eZfbNSM1M*P6-{y5kPr>;q*L)jiX6HXOQ8voxgzc}MG_cG973gYgvMDMjm53(B1a zXeUvDu}eZ?jzD!ta)I)0Paq6O;V(g2_X)}*jhm@>*>aT)X7)#~s?e<~?V>Oa72Q`_NB-Ur+!06{>(GaxSAb*kkO+@Ti?EY?KB~^c!`|$ zAj%~PbRg6mFAeAe_Ivi68-IRaB=`-jKxjL@o%r+lOf|U6F1^hAh==?>`|RT(VK5dO zJMrhaF=YTSOAVEOe(Fq_08%rR%~FhVn1gNp+;in5@X4oxt*Z((opxd$`(^ld*0$;9N-b)-^({tR-3_ zW{rg{JJ5vVO=m&u)JV@F$&zuf)Uk6{W+H^S5Mxkc^CmXnpCkjY0SA8#w}yo-n6qGk z;!Ni%$wXExl!O_`WQ#EbYiMY-hdlvMbQ*~G%Nbb2K%r#1hi5%g!HdR?oA?wTKW&N) z88So*BFp22L4rwG^$0)^*%+q~o)?H9VRiQ?QPGY{ZF|0n@L7f|DL<;V)x&DmqLH%sT^;voaRzh6DP3u zWgrn^9s{#Od0~!u6OB?y!aC_pB z$E{UPGbi?og{qD@^%VQ&%P*{IBbmp9*I)p=njdIPb2e34FsZ8aB@V-_B8BD$ZRzBCYz9Wz_Li^s@9@QqhkVBK`K4Etyo;G3oxhZz+M?LgxDd8hI$HP3U zw2_Fu`V=X&*n)3?RJ3FXFO&)^twv3oAfj}Y>}sr$7EPL3$BrF6&KDb3K!%mprGIEc zj1v+tYV;?bc)|`m@Ib|2H@Ax~zSs-O9Cqko?mdr+ynp}xcH)UAI>C=04kYk+X*>Q{ zqJ0kY;)%zf@UTJhxc~9TAF(jQMC)&P`x6+MMk+qzC936@0fgVn+ur&-9|zxM5-MOk zo7AswJ>@_0*6Rapo*YT@nfkIvFMVGIH!Qsw@BFZPoN9C5=Z?j7-yvWWv@dV2dx|=e0iS2pNQTD~KZ!K3g zfP5tiN>zwsLAnx)f#Ilf$i4)w^*jjqxz<^A0n*hrhsD%)hOsa4&Og_oGqfG94d@ct zCGOuO1CY4y1}%GLRZX~AQr9WQrsQPPVaPJuS^z5lu=(Uy{Yp)2Qd!DX*iJs{|7_f} z$<9T;_uhN1;w9@|$l1RZciyBf#V!u>g!9}-AARI|9Oej}!lS-VpFTbwAe2Dp<25Xt zhy9u3C6G=+jbprt1CzlnJMZGm52>Ex{R+Tifkt3F&(LjnuUEI8%~#xhn$nDC zVB`}M<2gZ~eNp-sV+O)+CHLOi%0H7QO?DN0_3G7v4*&;IWL64zn7+EI;a<7%o$jaD zP@$&o+QwknBzADZpR?`QQ%_a#qq%mGGWNAq}-g;Qs`w4uwyEOn5BWJj473gs7-nNek5-4%l=XUA=^$He=8VeDIi ze$X%_Awfp~ZPw4M->Fll$_}+ui#8I2&3uD%XY;wYwhs_A0NUs0t*{K;XXd0ScImY@ zS|@pMQzYc_E3Z&=5Iji|)-(bT17hNL-g#%YgMTSW1j50FgoLBqrUC~m{E8d|zyJQb zlElcDnN_&g&mKc$B_0>lnWSL^$=rOj`c7r}UF~>mj{ue`RkP`G{WoAp8$%zr~ z#EY)J+WOyrw^fx%E=zs^2wYO^i=jwUsbAq+6-;8RiezUX6*543EAsOt4HYH4jo&-G znm>s(J6F@uP4v*OIG$u>Rkhhdp6PM~tW;ou1mYjpaGGMsFS_h9g$F71=E8Z_vO`jNNNv^Yq|#OenKw({`(pSUN&V6Q#*a*fej zZ@snAKO!ao01ZGb5sc|GrrY#s)0J{IYopL`q^X~-MbtB7NYgia_8iNV-JZPlc(@l6 zW-Gu1Pzso=k_9p;L<@G|5Eoep4BWZ|=z7>v?Rqf*JBh0q8QhzOkNMet9Q&&nfQW-* zo0e^?N6+0P=-gm059n{1^6AK~QC*ynvT%ywCW zob}Omk^xvBqg=szX#M@TaM=>&zn-tTD0MLLw(ztuwS5H}E^(RLz1)zOZdGd6vt=r} z@%AT!tzW-~Wyf1#`yX&Xi7OIKuK8Q{HrNj&KB-V3hEg&Yu3ye z(=2833+92SfV`5Jmg9jYDShw}M;xIxW9AT2n$IXl6BR$z)d11UBTH{+di5$@6xML9 zqWI>5=g@AdsI^W~#mn4$>nY~6&6aKKq>C=Im!5f6RsEVbb&gw5Fp~$12|C4Si*j0oc%QU^VyGG|gI~+V;Os9B=a%E{<{Tu}cDL8~dUB zAKaEKR=Gf7Ke>hCcxyMbORl~_^|rUS4$1)7ZJX`v_8V@BG#qAr^fpYMwVptMV-NfC zKf(sTB1rhe@(&v}EY=^S#USN#&J|Z&5jz$>z!=1D;rFnQKUUi3a9*PB(Rz@XkmpA= zOroOTNEf`t6SeQ9^(*8;;9b;F!kPB+i}_>9L?@P2v7~uyc27l|wAb}Xe7CKS- zzDSyd_)QmXP*`jHy+M2b&%b$9YFf`%@|{Ujr+Dsuouz@)j?_9vZZ`Ky6Q}Cc&`Yjv9h&| z?NgEgNbEN@lf|`cS)NUtFu{`nd3P&`_|sOZLi!5PjVatEL-w!NUw_TL{b$Ym%Sc2+ z#yLv#Qj;JFrH=pv9^}`g$=`i~K!m)*`ii-3&_D=9uqhFLo)xnQsf=*~#4G|6z&_a1 zOCQyZ)EWCv*2drO9xTdxBxQ%VZAcgE7@I4ZC~MsSRfO_Y~hWiWYtSd7^-fa zB*NWU`&S^~Xg(G#UZk(7N?TZDm)(4WoqffnHd@sZ7iFl@Wt&#=f6CH%ijEQ<8JhO|wI_%jwTM^v;V$%Djnr^tzs^xh5?!7XAMJRDhm9;AN8_75YZDtZ2n z)h;hN5nuFABK}7SqwcRY*-xL9KS%?l`HH926VE?qJMX=x9ja`W@4o-OWlAGZz0u~D zA}ws|)@@X65T%BbPt^g~cp=FEB=);YO-WOZQ30H_sK?6Q^06Wdc4Z5ZPnyRCN_SaB z#X+8a@(G(IPWbh=-*M!8?s?~0l^_);R4AhL;=XZP$@Vs}?+|o|92NWGZT<`ck^)}v zK=C? zbCuxRoyKV`r%95nS-Y0CYTm+~8DY@G$>`;XB!o@x%s;bV)do)De3^F$n^Szen|eSJ zFnV#;eLipK(J1Zy@5v^ArVebSwfqt%$h+V2G)EUJVZfm8M%bYzpJDqP{V%)c!TWVI z)lNUPPt^Cxg|SKw&7ueE5A^1ekia7_R|PhvWGGeTGTGQbGL;Te$5xg7k_G$p^DlVw z)0BCz_a1vhGGn@jPxP+w3`nJSWaDfQVn&GH%$ceTs__X@Es}rFo;|Hin>PMn2Pl%F z2qtP11ia-T201x7ZX*s10OPf>16m#O96%s*DmhxGSljF53*;c4B#6NIGnDUU zGo-21TrcF;hM%&S;MXBBN%M;q>6^XGaN>A}DMxTH4ys|s0HRN|Q783?f7|PHoRf`LXatr?126)~Y3>4<03uE`k%r*9D+7Nj z&NW@qz@LB4vf)3CvCW${wuW0YvJ+1^!SX6Y!%(5e-ncHJzz@=Fyj>e@0IKgXW5)Qy z@D76q`Ns8hYuDSLA)ysCB76_F|G)^W-5oaU)j5iL2bPLCCu5vT!yC3s<-2jn} z5J%qYh}qkEn{BifP^3F}-kk6yk@q}?-r)BcMRriU*s09H3T32;mrfFI^AS!UxWPPPS$mndAX5?`5S z{Bp&(TD7Y7i89x*Qme`laGPzmwsu=~Q0!|Z-YWsda$R)+LN<2nSeO2T&7a?>_%|== zyMcXlQv}8#Bt+`mxwD%A7$X<~7^aOHw0>I1L5y4-v*ygUbdt!V2B}&5%3#pf)c~n) zY1%yXukPVpjU(h`zHQLr=vsV(ycS)P3aru9~&%GzT32B>DlACa!_T-*>?m6#y{qg64t|42pZQiii z(;tUh)w8*@u68|RJACaPiL&nu(6%%lK`b{=^^x>95K5%}n32f#u_+k$TnJKoq^r(RyfUb=j7fOV4$|oLqqD0l(0mBg^+^D2r_{~hLh=aagM14H`U|`g2 znfB>WZ^$T6ZQ$d1KF4rLc?RC`8+LAmo49>4N3(<&0TAWG20i+jM2pJK_nA}H=%rjw zw||B%5yPGJt5(|_e0NJ&0UI}OvBL=hB!iujO34Ibu)7`*qL=tzX;8IU1gZdiE?>Uf z34%c6y}NQ+>TlDgP4n!B>Zg-VI?0=XDXlut>9Pdb6qYRO|rOCSYAV zd#?1!5CEE-a?7ipr2Ej8)D)XDf1YjF91>Ay5F&K^*l`}|$~T9g=nyp@e2aaCdmun! z0f!$TH|hL^`1QNg1G*mk_GRk4XPyl_X$+$B)-ib+1SLwJ+#7K2=^>RXO8KM!iUB zNRzjEHx-DW*lM+q*8^vqaYhX!FND{%YggBKXJutMArKG?^((Pu z+$GD{@hnhQw1OBXP>Rq4f`oU-g(Wc4?tb`CytAmW0HAUpe_?sP_uw4Dpso zegHIJPTe>3HD8wdl@(5$ZQs6qJ_RNBs=b0HHoF9*L1dtJ6ivi8u$fLP8EJgrC`3Ooc zhq~_bPVKYEPE~?C;8w!-CJ+~(5M&Zwd<|(s#O9lvi~%4b%T*hs&VnhRxNcp#d+1-~ z2#>*@dqBC>rSDh3pNSJE`UBb^gy4nz6&K)`V~%n0Y7hu#&!slsJLKvZ5JgWu`6RYs zi5@0-`0(K^4DpA?NUNk6!cJ~sG~CgDwf;B?=^Tarb|7+};(uVi2jWJB&0I|i2Wkr4 z(15?%Q`n1=P=P2M_CW_9WJ#zNLyUwW8i_%)_CSmPh}My*S+7Mqu(bVn#%Jj37hr6Z zj*-nyPOIjvd-$ekUy=go6Or9Ete01;T;YB?LSly;f=jD5E)f8GV-&Q9*SEBv1D7@- zd`0^cF`#pOwr<_pr32fyZ}(4KZ|NXuh&X*oJ^t{AKe*K6=9_Q!_KW*$S=_(mXI0jb ztbp$3DgUsrfo>J!AC&;2))dsAlYna1gXD4nH^)A;7_7B|F;v$;iu#g<=OYP01D0OC%=b;rf?4aF%E z!|D){N4+qG^tCHiZ}M$R$iGYXE+J6>5wK!XfIZKU0HNtq{U=vIB@7WFoI7`}Cjffm zjW>ML6$1P+fQX-e{p(+*42gpV4YDh*ywVAxme_U?0R8(7BvB{oIr0HSHE7Kv0T6+f zj07M(J;Q_aD?pR#9=8`#KM}Q3ZD~(huy_$k^^&c3PHzN@)u^SV+5klLP}jF|)uUA3 z2V(a%at~1Pc`B%wHX8m)rznr zO46&|IXx|daK;ryB{1=!Tn)|~)N|=;zwl7vM94{N+nRg`%B;5yDOjigEDmxNUm!R{ zFh%}r#Ga_vt29p=a@4EPD84C107UWNL{x1B=U5q;&76b54jXBLEc6>0BZM0G=2{);Q6ZB+<6PEq>!XQDRR*hs@?~XE)cFwmdh3B2G2Y1ycR2}-G^Rk z(4!M3OmIUe&#uOkLW+VSHr|?k)_%D~{gLtCj2ScR`RAYawqAPar7aryYw(blS!W~w z;-d4n@9=R8&%IgN6*Tu06V21-q#ZNx#DqaBqLK{860>iwfO7MFc8rgl*ou83LdTHDFl% z*HEScn*yKXgcr^rs;JyyW&0sXVi;mLCg_PM{EQ7w6b?%5DuoAWCb-(Rp{x6J*5~-` zCR-AQHw}e22!{&9v_a61)vMQdx=ZOUmo8oE#kp~zxR|Qg^k``R>i&txPBbOH5d`Az zzyJO3_U4;!I$;nH1;KBAV>A5|NHz3%-F4TQJRSsJ2IQ}HCL!VJ-o1y-nm^a3el*RJ zNeEOPUN)7iGr7mrIP_2xLRvZ;KPp6p18&Wl&(3b+-^*oBqz%UFOT8t=*ZH0RH{uFW z78n99L)Dd$nPCcirAUAx{KQ^F9(yV-_Iu;@Kx~I^-2QIx+ad-CtZyvX)}de{=-oVl zhuHUhfNtHoda!P(0RnDrABu}TN)N~vURLmefcq^+SNhOH5BW8z1#~_5%`Z07Kk{r4 zK_gFx#~ypk{r=_tH)hP3X4<0qS6gdy^{Q2N)lYvyjE*Y%<@MLOL@rt-0BV_xG!x*? z%TWE5vF6=?55v7mBmxzvsdhp=kUuvI(MyUbf+26qR+~C?DxOL+p(Wz{Jv+;boke30 zMBtZbtX`~65k0UBxnk+&ynLJX5g~yy)2&P##$JLWACQo^P|*<5G^}DXi^0D2KtM!| z8a2u;x#W^i|I*JwlG2R_zw0e6fdG&sX&v$8zy9^FyZy+;7hh~Y{_&5!6Wu**-?}rZ zpMLP+M{O`^v+ug=F5+^Sb?x5M({%@^Git{dguMe~FJF~XB8v)n$IEavY_GB}oi00& zEhH3E+bhTk5QFIMffxZ0-QyEkyCOJ?Nkwcl8#u7RmXDAY1g=W05!q?O z(nLtbhc|$hAf67|(wLu$eCI?J8{p-aU+zYLL0<;Jaa12SoNCO99iVr~)o;Rt308~+ zygsGskUE2~j!*yqKmbWZK~z9(R(jZ$3b*{`7W?kSmsm+bF>Ze$JDO8ZJ;hxBwU*=s z5LX`&dQ)@|DgYsV+5KduWq53W3M5peO6%J|kn3ZG)CKYJi2k$f(8CU~>~`7i@zPS} zcmunnS>3L=8iQug147bel~pe)``BymOtRd?%WyTrZ+B06da?GAz@~(Kt|d`m2}XYh z4;y5M3>j!iA`al@G$CS>BC^98b}ob{?nekvfq@=<^ik)GgHmp|;RcVAr~8^Kh|5#^ zB=%Pp#N6CmJCY<)Z@u+ab(7QwQiU{E(0YqJf_A+B-cJv{tD7+Cq9r2^DPsbKOUjNz$tSZ41eFnnw>b-(9GA^zVMGC5AgV=9jYhN)50ycbTPRGJ-n^wLYstts`YZ$J<$D)znqyq|mz$JxuTz6$qT0T~? zfaS}U?JP6O5PwiHh5HuB4nS>7PvJZ2DUV`U+HjG5FwZNI9%w$x2z0}S4gQYsd{6T) zu|HAS12F<1Du-p4m71?bB?B9YlO=ZBYhcrMH2@;O_N}uF+hEH>clYThGaNao-0H+3 zd;OBwgF=>n`28Q;I8MQVgg~cEnc~DjQbPhcMM+m`!R|Ll@J0Ag>s}FB5p+>CBpfqq@)oEFysjmE^9?Y%Z%OM zcs;NW7^Lwk8GBQ856l-5Nd&1(n?{z+eIWpXBBA<^95dFxiD^-SkN~vV$6()kKp}vi zefC*51e9L%x4-?ZefsIA%~C|J6u&ZX6d{wDnQ1S)@PZpV2Cj|!-doXC!p*n*#?CzR zOnc_3CoB;oxhe>rO1aDl<2fKL1C?qctqdpV5;|45?NC6V=-OgSBy|E|D@vuL{|ZyB zeMCgT-hgagWIwQG?HZ(#OD(HymWLEqSGL%p%7tTeW~_|hb!HhZx@{N9UC+9V88u=f88Gv2L?Bb z2H4#Z02M*%zT6l4tg{D%C?&O-Fkyl{@x&9=_ndRiIUX>j`a<|b_eUPJe{YKK+Q)_9 z<-s7%U-2RiJM1t|c67=qr+Agb1-1lG-^<29Qknq+2H0X4AnqIAEiRo3l4jtRM3ZNX-pVEx) z1W-dgs$WS4#Ds)o(vufq49H$Yn+u7E7zS-fA_8I%r9BWM0HSnYR4olofP2FORl=q+ zL#t}xf(2HH5uf7si&NKTvo{=jg)(`e5A4#uqrY#_!i6?z(qz3p2K%800wkbuI{oz1 z?WaHesh7Htem>@yV`_K<2=PQ42>Hu*T%4Yey^!bFm-$TqQ z>y5Q^{srgT`0?XCwe9i8Pb9Q+7cW-{GE+g4C~_>RqRg(l`lt5h|6Z`O&iSStj3I3< zYm%7HmH^^JQ5RCN)dPt(xYGOZfbS6yYvTMh+cs?81kplrG1^^0lCf&2XT2pAQO=Nb zY>AE>JKm}&D=%-07X#rtgOgBr(dvR@C(+acF#;f(Mx!2eK?N{dB=wRNt8Mk_)fSI6 zuTpP10RY$05YXLa#Sj1_1Nzz3S37r;Oj!>+aDPLJiQT)K9*88$Lnl-a+-C8R{{GALT zQLu%ux}@xm$6q((2FOEECItxMP^=*4hivuTVjm=~7yx?{2SAcXOG+f+)hZ-H^FjXk z?xCy>WKKg})JKk>yJOH4J1SnvfEQnJ%!6*DGNC!y{lhG?)okvNg?;( zsKgCZ5%Yq40qX19ZoAEY4)%+;ZzJ?#?KQ#o1?{?ez}o5pd1H_vZLnp$I;} zPk!`lRus5)OQhF zd}1<$fVg?z&p_O==!-mR7pCvrtJJ`WaCymOGyBPpf9Sr!g(anS?XR!Jl6j{{FytN> ze#l><7lk%YU5&x6dqA6HaKzK!LiFOK6)srU6+{24AfF{mmN+4xu)zZT77z}*E`8sA zQTYKP*SR2g=fsHJNMJ~?1?27N&HP`&yk{}Qc?mN)BWVN?U%IT1Wzf9S7E6v|*=^#l` z=vX{Ockj~6R;|ysg}F;1%H?W@CxC2nqKFu%4pEG*z8sql^+<}4wc>vu`D5TiOIoo- zJibVH$Kk$RfxEII0a&+rqZO8w;G&%8@e#uJW2h8^XzqbMk8m{C{!3Ul25b|t05-^B z=ks~<5DHXTsuFz2Dmf|S<6Hl3fk$WuWePYgjo+-%;QXTQJwPj<2@7Yh$ z=bwJ+$+mpyQoH+(zu0HfKese&;vV_uz4poHGws+Tk9LH)ZS#5x1A$@?=)r!_o0sJ8 zupT{n*`R^_EN>ewa9WEHc?qa|njBcmksw1o5hb%`&vwScy#Uxl$|3q240Ng606^$$ zMoqF}{U*!XnipyHH@(4S#vW+Y9*7YDjoRJ&{xSt0DXXYhtdc&R`8n=9Yb`E4)i<_k zZlj*!JFks`0U#+TK@HHgUq8F{r&qgfPz=FUKl*X#7FR70L2xf!g}jj1AMb&H6ZPn6 zTv67LuSZ|^}=&O7fs*F#I+9&qG(Q0E82)lSG?#D>a$?X}n3_)V#NMT{)Ks7-{4 zG8+bn(;Lx@{saboYNv=BB`>=F{`+kpMteWM=BGB|kP-IRf81?dI(N30pZ}kI@b^j_V4G_QyvG*_wnJU&U=wtL`0+93YBHB6&XsUii{zZXdL;v>l7QSy89*C zufDGBWd~II;^oU&fH)>4GL-T|ZV2*MD?MyyCE10OtZ2mwI}bf?@6OpCA~bK~2D|Q8 zKZiq=yg^f?p@r)OF^KE|*#HDYfDn=h0g2k>Uw`ho=epQmQTD#}wXfOGp+oJt=bo#M zwij8>{ybL(w?hv-)Xq5L4C~spt6TWX%3rzN1wx)e9KPA_&lfjBS(3P@{_69&bLZOe zaQsrgY~HZZ#vFB|9d*=EHue3+Ty;WtV7?5?Cq&&F7G$r5dfoVgNLxGn?Sv>XB-KcgJ427d@b~y-5iP z&&kk6(mjbMt#vD_WD}Cuu^LC~$Ka^zJ%N3I0-1}7hYL(Zl$V~7Znyjb-6zkK6jx%P z_Ivxu|NURMFcAPcf`WA(gNF2g-07rm4G^k6buBwP+a7-SVOzO!rQL|Wy-%M$Cc`^r z+3VlGzo*xgR6wAOHWDJg2T}rE3(j?~bAI86gbe4*nPaaK(pEuzjy?8R+p=Yg&6qL6 z4M0ba9_@DuaRv~19$bs&PqjB_zxv|(8?LwE!-v~@@4e^M7U4AyG58&*0Um$kaqC0? z8@csOLGAH>mtSG!%a&OIMt<2Dsa8>1WNlk#x_wMBF*q_>wPC#_TV{vO5CP@R^|!{T zZtM1Zn}Jl0AOJ2QkX>%n083V$2|f?#o3(4#xo1O21yFN7`SNyxf9Lq`svV^wa!?^? zK6UKa(X!iQ@pz@BKnx|u$1mB{bFu5u(F2LmQH@wF>e~Y>D)4puVxn)MjI>TmmoIk_ zUMY(@RU3A#wOqe)c?b$VQAmRbVP{=hc$4|MC+&91-xdb{@8Yh47dxB*JCBaZwlU-^o2=;GEDQ$R$6 zKoSIn;`NZMVd6kz6a?oHB2?r-1@L+1nP+g>T5cbI{IMegApnWQ6__Zv-wSPqe}vq0 z$oNi%i)xREDjjdX{kF#~P;h+EXr$5=tFTd;|c!k7-=!EdHva(zc-L`F84-PeM z+&I&7;>@JyRs8Z+?88LF)24kCIgk!U4>oE4(@YW(yU$yF9O?zrQ; zpJvXS>7inHV?8IYSiYAYPf)b1au?Z;0*e)Jq8y^>4TWlf(4;_J}eub4X zHcD{Uwc5}>JTC$lDuOdvz|SB`f(OM z>3{gcA6yzBj$UqqvKJ7Nmpj&u9XlN93z>^xP&qo+^YY>E(4m8k968d)jvZ^AI(G70 z1o~a~$@MUJ-+paSBNz5x!Y%(3V)ebr@7Ku1^ET=e5kMHwTHl^MJb%IUH{59B4?*3r zZoL%{Ra0qvGs%t@C!_@-A$tw=jirJZF_c@kdX1G9!a=iEs_>~35$qy#)N$qXzue#! zE{5O$`KMqT5J!Nmz2c}3V4o=q;C8|Qzy9VM?$xlPfUvzV0I6~#ri~2+%^USwA@&pL znHiS9op8x`43$-sx(h^10?^PNZQT1~1VH2V_ddT(amWQ&Ge5O0KmVum$qM)p@c_mi zJ;6#=EVE>gMx0yog3tx-&l@_e@i(}x;v@kG6&vDM*vu3dWOToN_Q+$8*vkZ~x%|o> z+J=Hs`|ZuQ+0#!vY3H7Qo?U#&cdb*0F22WUpY&Kn6ekWq5Uzor$Nq$Rz!AzWIwL^F z`gwQA_=qEpFdYFXE1zP!OPsqFPF5M-g!C0DQigm|4@l=NRe(6Q$g+d_I42hr7{#BF zeH2tv!F*nQ?Pa?iPX7H#@1lE-vp$6HO+_rfD0i6?%_&UK*0=<2hkL&a71u@QpKrH8 z0Hj0kR)PeRWeE>)0Lc_8Hawq|{3kwtJL>|K3hN}XtkTjkqATP6thU+obz7@IYLJ-O z$_5P^YMZy`xeY)m0fK}W755>UAms0FR)E)!(0x`WZod%nk}d{KZ%BQUFnBC0Dz??D z*4ifaB5flQL;^AHz`G&3|3ug9jPAaQw%W~yKXE(bC2VrWB2*%dy#}pZ9S+d#aQs#1 zIty_H`^wQr+x$;Hu^(OdZFdn|wKSI`DL0sm#XkPzGc1Th$iGbLiJ*vTS;aoosk*E$ z$4P*U8`@fh81B)dhYcGx%qC2j;4XZfaceu|kV8x=0TBQ~`noR?`8V`E(QvTw z5a4nH+}rW=2JX*4HP*Jdp>MikhX8G`iGZ4^#@f}dZNReKQMkhjr;@X0EZ+3fm9&;n8bJSxEgL>zky97 z(|&*3Z|(96&$S|=5Xv)f6(Z3?4;yJ`pZhJ#UAfXZuYd%oDf(-`Zc?8r$L`r>4+NZi z5J*U$kzNA3e6X4PAYw*d44P-ku6XiEC)h*xKj4U1F>a8`JL%a50ra(3{m>Rn`M@5& z^DaB(YiC*CE?u21?cJ+~&Bwzcg(=^;ODB@y@F2vqR0P!!UJFTy5{;KzdU}QpBs*Xd zMu15WQX)jQZY3HZUNecjw2F0-0+F?COTMcK67cMZ%gCrMuE|cSiTb*0;3^E47}ov! zp0BdfS>C?yaC3wbVcDLajos1IJ)qq`2F8b%EG z<2(OQOlne!Wl&ZLNl!|N_Vov>rSHGvc02CKBS?vgoG&@f{`dUTHfqE$bkQ@zuT!mJ z(3m|S(YO#}z#&WIuWNEK6ep_lmH^wa-2eMO{_e?%lt}3_BvS+X_qAkUa{&SEMhxg> zcmD48_VXLBx6Yk9S|Wyd<@ob&Kt(2rfTSfG(fMbfv(5xbSCpggM_ezYjm+MQ3I3Gv zn;;bl!Q8n--jvRq`$UM8qaN`7rf=29;-*`rra=fN`1MlU0{3bC1(n$6&z)#l$hvSx zVRb5MyosFn*{fG*N^ztkA<4ifvepa>g<#yPf@2RgRu9AofX3?S1M{9|+O}zjPBPt= zEL-XlfI_UBeYyKSwhzM_#0h}akEcNCGo=zJBH70|-~5KX^!VfU^g|C=CpOVUTm%c? ze180c@7tue-a&2v!eMh%03nG&b(EGBTUj_)`hn?+mQkt@$=-;L^^AhDNX#FAu1Vy- zw`B(9M8{{Py^Cw=u;D}Ohd=zG$4gMX%5Xtjyl645dzE(TG2`rkyKc7+Uw_TMfy-nO z*ULAqg(xT{WNm^K0>}FwX*sQ?TRkSrQ>nsq4|$wJ7L;V7#KBDzPf;MGs6VDlI81 zgu{8804A0~@C|W(Zg>Wc5%|A=5$#l6y_>PRL}fkz?Ri$=yC`EvJwTp#7VF!8vFwtB@X z>)f$DdV5z~;l5UAr=2j-roa7;{qH|d**RbRnpNg)w_-e5;;_m$MYxke3kUAA)((+< z=T4n4qOJ1y{o?xNIw+)HDOEr%aCcYKD9S0&y>lmGFSM~L5U5=KI^!1Du3bB;Bv4Q# zQ8PykKiCEkz$uB4*)kfGy+L#Vi(<0I$bfl}*MfTjQRjw29JU1VMv+7% z6f8M3E|e5)jc;hvz7+Sz2!Lih%&g(9+lvZbD}g)zEkn)>KOnqG^=b58N1(Iu&6!>=GmG5n>cvZP>udLO|tX{l9%jz9rU- zd9bB{CB<%Uf*yzw08P;8`}vi#g{POSSjVvn@nkx-d>8}D7iV9Pe^5yk9sp&gu;7y@ zSHu8vKdU5BN-@TOquESf_|Fse!CSA}S*M@k-U8F6erT8CZk5xmtNjK4^|eG1{7O{j9Y~O}C|ZsTgi} z+i-tO<+o&X^}0DOiFt~iJ`S}=rI0uiuLym28QiY)_Md$G2?3G_rpbI3xUnPzLrs9- zEiVO^$GI&<-WD?5X+4BRwl|L_I6zS_$z~Cy3DB#i2k+ z=nx>RU<7!$ysAb@;YGm;uCv_O#i-~3t*;m~(;m>GV*uaflO*J3kHUeMVx^o)a1W&` z^@tq%x(WmLz*;VXp)OMm;I=rD5h3a*#5F2^^-4Qr&_KKL|9)ccz5I&3eBb@{ql+#v znFY@zobA}315$Ww1ggz$AY5BiSSdN z1LZfk_2!#x^-82zl3oD{LERc7)6-8p(H?*BVLRtr-?DTR0VkhuqP_Io3zo_~;|?W~ zUwWFAV+-IQ;xq!_-O+>*2O%N3+E7h8Zz1B!>cOZ_P+S|R|^OtS_ihxO!$0$l2r&LVNhXzzY!xnn zLdvD+G+}A>RY#EQU&Cq7F?`HvZ`G_V}ZZ znxgMjA$BjvwN5(s_8Dy~8!P@eR02XeJ$m)R{jPvWeZ_?S#qExJBS9Q|V%Qiqa8+|G z%}w&<-xJ81U-zq?+w!sY7ludVU4px9A~^u$9T3qBWMLIzRvix9lWM_42iTxvF-f1;*8iKuOR&hOwLv4hGGFMCNM;#4tIG8PPR zKx{R*U!@}Ek0WGg;nJm6LM(xU2llhO{`^P#X!6_k=-q#^iARidwe1rR|HrQS(U0wv zlfPo)ju>M%+;F2k`siasT_eUiP>EPIB&n2&K$hEBLmBZol`qVxUh-g{B)7hC6c?Fl%=TxN`y zEm>?MMjgz}2{vcpd?yYwQ4u6!_?L=4zcS$HBb&y2DJFh}CXKQqy4?Zq%*)I36xTuE zpEyOxVU9)~A|902z6>3?LMm%nttB89mWI}?T4y?J2U;~R;#0G;SlAw%OW9r0@w;@6Umo2)#p!a8KNCa}=icJjny z?d?gEZQ92(?JxJ-i;$qqKAtw+v)Z{xxJyU7{Ck(Pac{F9|MC>yFwd^au?F+ zde~N7(MGO~h)u1Ih0Jd;Xv!XVisVvCR3uP#K0(LKHg@EgaW>`s_wBS(PqSCwdedzL z6icFr$aN_xiH^K;moDWYeEY%1PUkY8?v@_O$v_0 zsZX#G5C>t_{JAaxklUh5FKCO~I>-=^_WF{o5AvsB<=8zasFEag5we%ipf+j48~pOK zdE&nc2Q9)>(xIH39HKwY4GNN-b&G>9kU1@`gjuZ1_5ti}Pqq zU^Z3T46@<4-Jrq6svev7~gxxR5Zf>(*|t8*jYH?zrO)8!=*poj`(@-~RSC`+Vl7t`F7*w$o@ZM0CVs znH_`Z>wy_FW}rVOYz$nM)I~xbowD28uz>?SlVz`NUCA=p(YeYlojUNl;`BoRfVNU) zxR;hpY>5Kf!PF8`mw3KPNVg74b|Gqy@y~oyx@1p&!@AhEEf4P$NtLulbN~U841L@A zm$@Y`0I486*8-j|iU_EHI_^jB&k`hyy2xcw!HMKv=+cIrr8N1O<8*8nfZRfWduq)c726tR13TbYMfKH>`PpIuOOdUYZ2c_G-m9Xa#P*0L5;)!N( zTIc9BgL=oR81z73z!YbXXdBa}_^}MC&_^Z`88ArF5!`;jJ|i{@`AP?ei%0d+@b3w5 zU~#w)!g3%HAg4Mvv_?-VO=$^n0+QIAbBM4evF~>;x)3j;R2wpAuuVMXNTdh&d9z6u zlhXCwcPH8Pzy6ht8a2ue8h(%sKWI4F2@kd3{{A-m_k;f;VNnU_Vo!`nM5PZ{$HWSb z>;YN-i~ARH6fzwHo5rF)b#sL4T7JaU>-fAxDC zeD^a*Yg|RUoKO*ZtAl{rW&J5r?vRN{Mp~0yQQUvTYnJTtx#;`hRI2nsP%Wu?q|y)( zFn|91;Icm9U|Jr;2!NI|rVCla>t%WK(9_Sk;avsDQek)-6SN_RxH^6EZWjZH6KAUV zc~F}$=Rr(Two|KOb0x>CCBWT{8ami^Y~SV)#^T}J#*=pVcesdEl~&+sP-SO+KF^-~?^E{l6HijMX z{!Plj^1aYjEMJLXAPIjUC}dbyipnX!q};>eN|as>;ZPM()-ELsH7c;bztEm)Dx6cI z6lzW%4AGo`(Xiqn#IeR4FdF^>L|}FQjd2jBuVk>2vfJ5bpMP%CKMf@TBa4OBehJFH zSv$+o`=b|-4n3_sOGJ?jI-hyw8DBeEKV7?ajjZ^L$S*DBJSHP;DI-Zc;8$j)B`0vB>*;3*|N5B?LRb6T zQ_ondw2(V)5}VApF=On9KmU<^G<6aIV;0+!Pd;svr%bT|{KoZqc@wN#w$e5ep>Y0; zPwnx?9>YRB$t}!BLrnDQ-5W0RVC$RH*Tx?)&QcT*CP}**4~I8Al_A8QfYd>s75q`G zb8T`C+^ct$Au>z?LFt}`Fi@dF_WxhG*9o+#d0?A}SGf2(;(Jq^O6;Eo=UIT4h*UHm zeDHx4L2YHo#SViqA?e~`>HJf?r;CN4*b;1Jx0|48G8(@+;JdC{Dmmiy# z8sJ|UF%hM3s$IKwfdFWWsHxcP3W|szD2r9+fP-Bq<4D#m>5k7;prL>v0yqYhe%0J!3+>-oCs(K zQDg$$U;7#Vq2?b+_jLMrcJ-PbIxslGjlbSPOWB8mQ`ni@KE zsLvO9j7*v|DY9NmBEPhh^B4ipQbsbgkf&mRbX*>8QB$UUXoH6jLni=-(ijkIB>VWT ziY;5LZ{NPoj4#K%=)7~zwY%@W3yx)|bA(_6H_R#FzF~d(*`WuGva_%UkcIdAQ>WOc za3niGATtr;uO=)K!I{{@RMsUhCGlFIHp!T~zCf-RXpl4~)iy{!)L`3fHxO(zflQ#Av#F9hEst z6%tW;*IjqnFrrF^h(U-M)JCtr{(5A6BcvLUmz(!_i~wlf<5#=(|1K{tyP9R5z7Y;d z8>QO-1RI+^qY6NjL6yS$t}LjPr+r|LZZ>buT)XPZD-j2;#fGrb4n;RS73qek^AtF+ zy!9KbaLszlm7geO}=Z_ZZ4)CHf*T%fhb91gFlg|bn*dLf}%#&T7a-P*R#I2!RSd+qA*(4JI{{(i&s_{g@bUt`&bTQPrjgy!sPb$f%YDTMT@FE{#0xE>%! zooywGTDwl29ns!(-@noGS6Vw_KAdV>3%1+LIkWA5ue^eHL7sK&+{NbR zl2cx7XX7pr=7EdbxOSxisgblgM9EfNtHo*)`W( z)NSHH3D}P06O>TIUY0%Ze8hl%V=loHW;iyTr#+LmL%fB z7c$b53tv@;Qs(*agJI)ZW{xGZhAJQeHWI(W?JD5zMW`yVP`PX_93kSP0M{tuwN$}~ zxL@-n0Xew~#npI$2$ZG(+25!eLHg?B0mR|hA9WFdL=VuT0nV@dtSOq;kasfw9`vzc z9M3r84EqC#$^@F1!TMN;v?u~F9fKe*eq(53VPdb7$K9Kgr`i0) zi)`%Z!`vXS6s}d#0izwVu)-~c`u@f@zF~iX04PN-JfL@9`(V;!JLjTHE$Qxm*!v$$ zwGxc5GO@HyD8cLzxqQfu0MUoLU$G&91lffxj*!GM>XOb5Nnz&#aGx&I9igzoX{l3F$(^;;hon* zF)HG0#nR=TmbX8|lE7^Q@WBqE_KC=Hpbz`?>5CTt#2@3i0qM`cemnz0^ET7D+Ps7I zhaTcD*NT}7DXr42FVBnXufp|o`t%R&h{FzLqJ%~(D5LthS|?0jEpoHR9Sp~}<-#`$OH`w!K4%hLZzQb`A(Yd#OSp!^gf62c&{6$9V$AVvVR zurXxjoObwI3n~JP5Tp76E`jIg@FSHSO<)%o`2>!`znE9 z{`f?G%tb%K;I76$qmk!>&rW$Nb_78-DNz>xlUG&cFWEN-?0CI&~_> zYg6o_PiGKjHe}ScNlBPOHL12c08haw5-WRlD<*mk&sAW zq>pEO2FJ?K@NChJQn!CAhx^SZ+agW!D2qaLvOp;FZ8$_+s0@{VfoFDMEl4wV^3cO;f`C_uuaZSMl_%jQ$jGr4)65q!yh!ced8({w39rxL+eHQEVK@ zv;u>@S%kUn*seX}mw+um+fZD8r~G!^qEa~V1SCj17@yB)&a~6NdaA2P%F1vq zW*3}$jw9bH5PIj1*|rq}z=aDITBiv|;`kVLT~d2=V4w%;cLT91Ec;!293~F5bt!UL zBJZdG;Rw-GLJ&A%P{3~>X}O$f;U_}~B*4)nA|}p2Vz7<)?k5~|3_jn9cG~gB(ZN+V zcKkRuE_~ySS8e&yT+d|p@y8!oCdOf(W54kHORv}|C!SLVr@Qh-9D7WzH(xuhAo78O8yG|$uVP#Bie!*U3@3^lONRZB+# zBG$MH?q4m1q?)ef7A38YY~NVEydPYUeN3M|ecVn%^HGP0Pu>h#(@(SM_CN<)W_R9xyM6rT zJNDLpp0Xt%^r!y)pbhUo(C+->?Kb26$u{e~5A4%d-m{vTy) zWBu-Bm)J=sorEm{b&V&O4mlHk^|N32CbkGd;Q8mD_l$Jv8@Xl$389318yfro?c{p{8g#D~qs;Nf@ypiU@8oX;DO4{>|s5h_Z5 zRaY4ks*Y|%$Q%)&qH}Tnl^o@g0D$y$U5G?dig@OT6Be46!LhU0Mmm!raOltrRnMgO zWJ|@M6<3#<_6c>>NZ33QD60~QnL7|5`N+dAMTW2HIRW+nNx^yOO4I*kUbLeYLjG|g z%9MffgcDBiis^eWZ-o3c)=QQw@et$@HJ=`F-l9%p1VBp|&f1IA>^?0*8RxwG);q-f zYzGeEn~rD(+EHGDkQ^ew@;2MJ!w61MZjI$j4FTuavwcVFK6I!RU|ja# zqmSFP>CG!5e74kbffOiCf=-jR!({m;PiUVd&94 z$LEMY9}o}0v*Axkgj~E20g;uJ9YPk=MK%f&{R?>n2PaM_C`+K!NqTQIfo8_0En6{o zU1F*9=}v;D9<|g|(!m(U^K2qgDygOBEtroAr&?Dov-#EaD6P?M2^;oZ#TdouT*T*{ zciy?n_iHTQCm)5t)jeji24qpUOo$Nx&3#-WkX!`iJ&k7h*9A+^(ZLlbi1TF=YYreQ zcLguphyZN@+R4g2uRBe;%F! zh9&t9BBoV=#E&_0ytOBQ%?@HMh`TMp0>8AlgpjpcApp8SAoQZ1%WXS|rwv@~Dd^-? zV<94CNG#fc2o{Ng+~Kqk75xsyIQQpSF$6;?*4jBB$@IiHJO&PO{j$WZZ@&4az4Gd- z5G7S`)LE86+U399_fLZBZ1-3Mfqq(LHZ=ssdLZ&1_f(*4ag93ogY8Lqh+vRiKok+&+9o7nDTjc~>DJBKleG|0#U6UEj-S~_ z%8)!R-$ms6Qb3!2<{SJLMUmy+B;5vefm@>Fvf;Z@vAtrL`gx97rhv zBBY#+RR(4Q`}VWVxVCNGl4tQCjUxz6tTFLScpwsOFhz(^b08GjWoIIG{D=@L`49`~ zaKkbvGY@=IS}p_=<~Dg=G3SdgoD(rHXwX3W{`bFcX{Z83u%z(Nyt#ATrAgxdriLII zp@QQGVJj4{Xf;)B3$`5F@ocD~A0z?TKoF)CNK^8--WFp(K{oahbQH#bJ0J%8c^1Fz zr1F(bLk2b)djg5)#l=f3znM9cfRUc0Op+jMr5u41dJq+LfrwEhB2pdlu-OpO*Su5U zA&HDdh*XP_ITyj=L`(2lSD}r0jeeGdMIeEe)Izd-$Wp)hK-9A`>K=|#2vp@5i6f4} zX2NxEBD^+Q7zaN0f}*JB`}gj)!4Q-G6Y>{lFIQN(5<9V0tGwWvj7}eU=)@aO3eJeyf_t+EvC4*X;b3##J2T-G$+MGfglwW3(5#kf_N5*JJ z9euQYPINyZ5Jl?JMlKRzIdRw(gFW=jftki$D&ky)P1XMQ391MYQ9>vZ8!MYyJ`#e@ zKl_Z$ky?QmQbGI~5&`2Db==X%IzpC?dB>JbHh%08&egv3(#zg9alLNV4`T#6ssf=N%6tqRXvj9p!De0C$X)CZ+{?)I3ZNDZll8hh4k%_z2 zh9(2GXaOO~*I$1F_q|Ons1fd|z_wvvzX6{3rvQnEJSLR8LTPn9n@8HRFn6`9Kh!>tyvL_D`DzeS;&3jUcUOYI*KgS1lA3bL>q_Lo&Kxpci>IHz zKuqd+K=pRQSww_f00nTtTOc0fmKhK@ew}+2Pu}an9FUu%M<|qJDmeVcM*Jh>Pg}~E z3&{{wOOZ&;CVoUAgr_iiLspK6hh&WY${Q3z! z68(#iyzaW|FxX@@M$VJ)Qvm_+@WT(ggh&J_Fqb1gd`pY`Xvp}t$PQ@1je1FoQzZH9 z1@o|eFK`iHjrMwSo+z6Fs&tq$(Wc*-pg`jG))AFUG1e8YTQy#|V1bpB`Z%=R@SzR% z0D!y(+Ea&i7_W(ARoyDs9E!yW!Nrdl(9Z*_NGvR!p>vF?3(|^%1`n}95b~tS?;_%c z>q68m_qGo|{n*M7pUT?Z0fWP@pYb(s*P3YQ zBME?_+sSHv;nKyHyENB+aK-nnOQ)`s5od3``wlVdQBxeCKG~aY)&{#)Z38sC+Jhz5 zS9ZTn?K>b=F0*Vz^b-FkVVou|T6CZjhdir*Ni#nFgllm=4|;TL>z{}YLdZM7ME=aq zKicq17{hW10EL*Tg;3o;b)7LimJLhuq)CS$6xC?kKscE;4lhrU-Zr@&%d_XY?= zu>m~R0ezqBdUh|V>Heq<^q&KLzL_kFNf0LKvUV4dy*sF@Pa!CzO3-9ok94cnEny02 zcZD|EZx`~W<21HH=8r%A_!nNRF$=~`_sKrs(MKN*%{|7QYj=L(p#y)R3$Ku#tkWKj zZv2iF>%Kuq-nwsP#Ga1M9+*P4*0WSQ&4yAJLTH0nS)$CS0xDQ1goyxUdz&y}g3Uw< zFz%=$ZPK(4Z1~VYwtU_~r_|GRUtNeUD7V%QRp+~QaZw~i1!X6KEDjkt3jN`Guu?=I zgwvDQ8Wz+JJ>pQVzm2G+(2_yORfMfok{i+)+6W95`;ok6{+xNRPAQfGhdXY};Wh7FU4`LXTigoQ*gA|6XAzijnl~2!06+jqL_t*Ou)~kw&VA^BUGz&s zFNb`q6I}GH;ZpLX3Tz;x5|FAyR^_rvm;0PlJd&`uodsiZzw}3ehwrF@R{;z-|8u-@3OS-FXlfEE~+x zlS350dg>64t{g6A;8URAdT|WY7a%-Hp)Ym()!<2tgILnFfprZg8;Gson8UH2V>ZW9 z4)j0H(#ON$O4KY08(nX6GU^KYR;y`9+fBh_b{jIlc`I?oM z-FXylheS`~xlDO9P~szxJ!!=I5R#a_`T0tIL|T(MzjNDsU1Xc=%GB1 zNPNnq_wC15|I|9SZ|CX}m9v(30%eH06$ZDdA=q>S34plrD*8u~6mj&5@E1b-aO)5S z^4Zro7tj!oUdaZXf>fjjZj{Q%xCLFj)F7U9FK8V1)CKX_M#LjIT2J7p=^uaW$WJ72 zQ6bjse7cHZcY7^_p7IbRKsd;dvn^^LsQ^@85h1lf_8sf-0)aY3(tyidpr)#QV`F`1 zvZ!aI{}+gG(Yi{LF{7j>^#zs~bg$d3DEEPk3D#{uB32V}YkqCAZ}&#N`IcL5aiTq> z4vPFmgiEMnv>)Dm_uVeV3(waCq*2#1A8Bkg=v;_YNSB3c^EpC>B+LrVM{$hh=*1x< ze;9|5@PUGC3O=rZg=0Krzvj3{&o%w-pjyP>K=r_%S-01b{yX`1cmCZ@oOmJ&A%(?D zh+N+=>)tdERAp+E8(^^-7sFpvEq>Q6C0jPyaYv1_yZ-iPE>v1~Lc`9PJ3Ewq^K)CcD%X?PWb*zE8#ddDH7l$WL4@9T z`Bf{xejp9vLq>o*c$akQ@k2G9m9dQ-?Zi6BiSWN1{52Z`uqx3F~CvTB`r z4}$)rgQ>QmXBQ}g-8%YAZI?(_8@AL1l@UnHiP~!NDAeLoD793w`E7y#kntLSZ2jhK z^n1uEJapG?{?dQtQb$ntYJERagRPAHb_g^{X-L2o5+!q8_6wDjFptzrZkawGcT@ZU z|4B$Y;w3xqRB7G1m38US-6~LHX=aEJ+9kM}kU7gyS}upDmq_AQ zbz2idFA(@)QX5K*^t<2v4)2dFpEKg@YlH65xXJ*%KtjLuPr-j=n5%;_+JXFk6Wkw2 z3xe-q7s0LE`v&)xGWRBMNGu;n5PW`$psfuGK%_Y=B2vu5;K75P;MJ$HVrpK`$7NWb z%Hy#Bb>~{8=R9n?`_XB|KQ!@c>en_0-&xQ zY$?~UJ%jZBuskmAsJROkn~o8E`&sGs(hz4-Mjj&fH zO|p&H8nkNP9$dwSg}8gnp@&%o(wcQh83qp?fL*{Kd*Z1lJt2@sCj?0?#;~ii0w$ra zmJy{Q(k1C+7n{U>?4o)XH6FJ~fz$vVikH6aKVSgo<+cc7PF%mj1Ixog?sg?$E{!+I z5S)XR9$!A_ipP-8k<2EqF>nxN@ddyuLtZ7sP*yOhfrAHGI&Oz+3GkGRL?NqP2dmnV z4^gsHs`7;*cwZv@TZK1)kbXXMLF%41AeF#SG4h#%$-0;&S4E@_MR+x&HMImFvT~dY z;iyj~g%R=jMU)uvfaboyrCOo>m3>Af{aIX84w9*sBtVvc5wFg<3#pG9HOl9TK6^pf3dyUyu&TkI35XNbMPn0usx2y85L}x_6i~HoE-LK`{e2oN{#LXWKwuq#$=a-w8BariAB z4@}=ULmTFhL4)n(S6(Al0Gt=X*Ph+FTQ-P24~c<{uyzoRHJLz7aUh!0Pe0uWfcYTv z!HBzy@)6O32sgvMZr_1A0jZ;qqeSGzxCSmsJz>K|_c5hO6t^c-g640^q6vkgI|giBOCtP}WEfRZOKqh$S>ncUi~C z{^6WxI)uYch9h0?eH!ueo(E%>FWGNDybK~8DFiHJ{Lg>>(~+@|e@x+ciU$+1_+WU6SOf?yr!_uxH>c6bs+HmE~-IwyhQ77oewvbOD2?VNm z^qsqOw1u-5V4Pa$34qGsvRBZzOYruP$X!8y)RwMYv6X@#P>Ns$45~ofF7Jl~HqA25 z9r5m_fpH=lK>A9PtTL$#LX}eM&>4>kka!io>^r3hUo1$L{N=n$#&25@y>1|CBRjgy zhY*~KT}^G6J9n@?IFgV8Qxw^YrYEo7MYYf6>Eh1@` zhJ>$!qk^edeP<(|oW=W&7xEW3J&@QPLd3!R2#{p$Itgj&kThrVq*hzKX0^TX#v69!l~?++*I$3Voq~;($_Ws=-W_@F4@dmb?|~FRpTT={F3|6) zM*#XRqC?&%C!Tm>aJiZ=&;`{^UMpgR0>VLkA|gZKk8iu}Hm|eF;>d66L91>=?BoFT zKvl(5{G{g!-#<<~`rJ7)Ee(;i#Hq}R1N74UP%Qh5Ad!j-ksW#DQEph54H6i2&>%AP znQhosWJ{LiYNeQO^x*{>dUF5$m7jSMgp-o^d^UF$2uWG`aK$4faXN;1{d)Jd84CGJ z0v{m775MERjO0Q~SjbKG0FuvVrlG@MzXgOMT{L=e?$<)^*0q}pWmd0W#|1@{ zQ~dlA>xbH=ch4LXGLb*`Ktz09I=1u0o|=$C3Sm?SZ@p#HKm7!PgnaaDSn~7Egd@>H z7lar57e4*R1NcWG*3c$cX{Vibn$J6h{~bL##GUl+*WZ$;r}XJn7?ur%*iqaCh3wUK ztM&_N3*>rGp%N5$!PV%G1f`N!MO9Fi@8+W;^})aUfNTf~R%X3SjI{l)FD z3_>rC%~Z%z}wQt&B#57z!n?4r+^<$kor;4OZ1XxZ^ zjz`(7mz$`jPiPAHr;v-jmw;4C=|e43nkvBHp~*m0^qqRU+9`y0>#eu?T-V&wA%wU) z>7eF`_ffbB!Flkk5NNQ5RF2#|FTVI<_XJUv$_p>N(2>6$5AF-jBR_Rs8v=wcLL@j3 z?omB-_&nyKeh;lD^?P`e3~uJLb~~Mrfzi|R>K8>O)ir(R6EZLcEw=|WKcv5`s>&~C zq*p+-e?x{%-D4_IpMzR?sv|N`o|&KPa{OE4C%J4+h8Xhe}X@Rq}vVba3IG} zA1@lXv;zU|T|i%U?WU}JpmUH&qL8^zyL75>i4r-MVs&4M(SR>Z?$>h?`FC%hWpftJ z#|wbKKRkQb=+WF0qSoEZ0OLkk#CPf1#SOMTnfV#IX>|DLuNB3uQldr{tkfQQtHL5H z@4WWqfgsRvM}$HZZ!az-t6(oe3wLo>K*ed-LRWq2+AMhdfP*%#P(UJaB>0fiWkTvw zYsgljh<3M!Gnal{$VDm>Md~Xe@}FSyMpPwm|J%^{=V8H4fPHUEJpI@T$&X-nZHv zmIkRN0+6;fHAtNjM;PX00#lVjH09aOt;tLzoaypeZ^WFP2r+bV0a`CG{?A z|KIo=MRrlKLT;B`cA1@e>ZvY)+5fMqS)u|ANj()13^jjk`fqOh$NbkCk?n_E9d#Zi zG#11NfTka#MyNs6zrdruSxuYqv8w@s#4(NV@_l+mobvcRlz?PGfqj%qpnLbOHh%nQ4>seeiE&|5 zJL6lmwE<)c6pO`IJMom0tyiBMkF9^u!3W#H98MYFpMAs;N7!-4O>}BM9oq##BnROa z_Ti5@G!n6UHb96`)vc)^ ziGC`<_uuCs1d00bAPg1325ueR(E2%|qc65>%X4BiG#k8>Pa9g+e!BmklygjES$EuV zhtGL8AdURt0G#j7wRHfh=VPq3s`kO>i*RJ-!TtFE9x%uyIlSc$Gsfq zarEPeL0vsiWsk83Zbq7EZ@l@A&HiAT2U{r>J66}mS63NLagF+li%z7PWpMsyo_d;X zShLPr%O5)}-reaYOqk$0;z}aPmE&8^6QP>!kG+?^sYWm$q@G>6+1eGWT+FKgK?+zS z;-pW{99y$;ZHPnV?cx^oUlNQ|^z*}r2)GhtUx|dE1QGGE#~fpsJgR^+vOxEAwV?Jm zI8x<9u>n$2@PemK7hH4^R`a>my>~Brly|=*3fedXGLWhdXtN3WPZcS?}C+AKmsgCI97hL*6)Q&R;{&9XV0}^BSyeEvl+0t zN~|1ppp?7XbOIIwu6y`^!M2)>w-7}3wXd9JPd@#;b?e*>iAK5=Z`_2z8$4r;O*ewT zaUCzMq|Al@-Gi|oJ3K~){d)AW))|@Zf|i9*pu#IBB3hOhUf-2mrajjCA&GWJ_w;}09{I%y$xl+tzx+}Y!gKVvVw`IdeATi?RS zk>o(xZEVhhh3<1MBcD%Z&8cp}_kMnjBch<2Zo1`Gj0p*T!=Rpj{`qjOp-{HMeTo?% zqdY~k%juQl?m{C+Dqe}9lOJs(m=iC)_@cWnNwldARESQ7Z6dVRW1x5c{r7u9oN3dh zxeLo`qqL;kx_kXYpFTBJ? z<6`+C0eeKq2*I|^ZZ9m1;b4Ys1LG87XCWJh0+6u+LGeJYWIb^Gc0#A9SQ-kRRf%Ln z_1rCJ5F*x$k1_M~6O3MUS-m8~*P3_fYkeT-flSyaei4bvDNs262pEG<%WHJ2>9r&@}$C!^aPT#{@3 zAOJ$fRiRBlGjCv@euSN+-}ZKKqEIk z{Vr6|4}wW*lc%3~#ulwuW)lf?bn!(O+eQK+C1YW}83L~zX@fN!*&Pu3<9l8N0jRl~ zEJ6T-zD-*~!B7Tc4^bs6N=K|;9P?r}xePWyrD+Zs3nscx^k<*XaN?mFIoEDxcrGMj zXd*R2T4rk-)NcS@3vkZ#l@dTzXih>9lI{_yPaNf^czR|@b|lqM5TX=s@fYjm9o7hc z)aOo|Vfd?X;F^`=v5v1SF7$|&9&BMx^-$l0`@`o0WtP&fwYzLj#eDI1&4#_|8)5m! zgYtSJHGAo$mz)p{uI=hGK+u|(N((HacH_p4gwe*PrWW$wRT;ax9w2|+Bg89v1i9hK zEw8CS#IIZ;ee8BtLX2{=BLGsE%r^xal@PzqHJAe5tQo{`Lr>+B4((2AtR@WR)n8h8 zl9m^;0i-|k{ImAUpZ>^$p;WOk?uV6pU^^1C=k@n~l|FM7Gb&qeY zFTC)A{qpLcSsQe(-g5tgAvvfnen&D&^DKxUbo`a2E{>k|!4wyHcJGd{ zVYi-P4m8Qd|829{Vkp98?YmpCaQ;#OA9> zA)ExEv7J!A8`rJ3t%QZ1KYNZ18aTj;w-s0lzpW+&v!XE8n1?|Ho8Z$uOqh=eAc55@ zR=VC^UKWZ1UW9!`8j%rq3+m6vHKaL>^gwYfe46ikc;`UuymlbYx>4w}LBSf!skmc$ z+UVfoZaxD9t+dVxi>!5{tel!VksSMOim3Nb@4fe)J^0{*b`dH&N$w)1YQ4+Y*BeFf z6e6*ayJ7^~z`0ZH%}oN3%%-%R!D_1oe8UYlxIxQ94?RRK_318}41!!lG`2tIf8w}_ z<7XTXafD2aIcf2r1sn!W--nAjVG;W1wSOXiYKpu+cPoyDBA+&1|&&!HjT)fi3 zX1C9_47jUpgd>)3xZWjVK>BX%-$C$2cJPp4)(erkHkd>$2IA!Crmij?@a)C_U)@BQ0dpMzwQQ}uW%pc_U+pfrEIisegS8sSoRW)%2+7S z^N$%b#s&=<KW6OXlJNJkdsE_E*d^|#-$_oq$4qk=3Z3)rWKSUHlQCQ4$HCj<+jq!zCN z3HR^O6KM$2Kd8iNZa(7uZY+o!pqV^Y4-jrreV#$WrBAJ&fbiHKw%9(qMvXPmsEIAH z7wj!jV^=gHR zX`mO1u!$6?+_AK#GRL3g9A$Zw%0v*zm%vHHdvBuH{*1i$-hVG)OeSA^Fe*r2Z`lk5 z2LX@(lxc~j+#K-|A&l_8!|%OM&qKPiMLb*Eyk)Y2*RF5P+uVmPar}Xj=&|9R)r}Sg?NJs z5omvby$9R&+b4*>9wMIvkFA)FmObm(GKmPF#C;CVVFfghJeC4AX z%t5wt1~AepmR^4Y?al}M?Z%s2eR9)HH+hKDGBGfV7B5$SVR-d(2Sm6!x3&emfu^BR2RHs_I4HRIg zS;BCWfJF@oY6ka$px#m?m8g#S9ooqYqOF$yl7@&F`m&UILL5k(SCU{X!MzLT&vOQG zMPfLGDvk~(b$C2idCQO^F`fu@``g2Q8;$wYz6wEPT)+S@mKnP+1=Nc%l$=t_b=9X5 zb5LRm>D&tn3d(5_%y4}I^+GxVlTMkatLk@typHPawF;K2@C&F26?*m6SKZ$k&J7L+ zt{zb&;!XB{KK=C5UAF^w2jHHgPVcDGQ8ntjA1b!{W=;tH`}SLw+p4**1Rb0Eia2Sq zQMZt&q@N4t3pti(?GjQMzTs*gQU-cl5qAiBsh(@4P`e#uNcXXbP?@aPiB4ClZ?(}j zysf36chRz*MeJIlKQc=brqb4;A{;HWN<{2fEb(xb^o_gj)Ys#%kNNZ?tst9PhKOSG z_1fFtuDj0edH6w>H0(KGpgkr6*k2<5tSpIbGhu2Q*OVpBIEWPEL8J$j0rNHNo(Cdi z1$oFJhuA&$++&?2h6PSL^9&pJ<(KyCv(LH#W1d_)e_pWA9(w$7JM#DwtXNiiBSyYu zZ53@TOZFgB<&nX72ng3zFJz?lPk`bph?wIB2k~Dhbq&M~n+<(lA%Pc&!K43$9Azg# z$`Z3i-)A+Kv`0+9a^V_nNFl{pQ@iGd>+FKF&#;Fc8m{P$vMJEBgAW>J+wHQe?W))m zci(oq>=Tyw&V>{r;GIyKhB(qD?yVvf8RgkR9x2(fTPW1nrR}N*G)R#VBNvS(;x2rPiaiv=nW zBw_xe4*&3-z-Y`9qlO_c^Mh-`Pb_|~kAJ@UBOv~E{hv#|W_LsIX=Ez(kt~Ke4=aAo zNkfMYwHt1@!S$c03J}8pyhCS4fG+7(rCq{>b^e%@`43hyON7_n9Q9TVSw=Ny>?X!< z<7kSAP*WIpwUW>O;9u?O#%GyLvSs|1X>YzYQb;oG60^&OG~x>Vay#6e<@ItA>w++cx7k}U9o z?N@cb%9zA(kcFi0*cfGi+ODPm9SY-}ys(`C0+Z@L>hKTW35*O9I(FG~oT2U#bCMu} zvG1=wV`4WONV!_|i_5UZLVTzKcHMn9Z@YyuPRq~=ut<61QNd0l0PXNbT{diwNqhHX~GX(-&rmL!iEOs157}U zHZ&?y8)Ni_5g(BhGo%hl36Q8MA7`!=<*-EOkjgx@TLhA)SVF%OuGH>P#v9f@WO?L~ zNBTTSS7#5d3o$W}+98bs0!<0uN$1EoW{whn15X>&XV4p87{I*OG4LH295ybx_S$R9 z@rADMqfbjuwJMbN;HsA!?=Lmx7?tiDac?~+X0|qd(SF#n9>En9|$!-fsBGtRlt9)9u}+is^_Y)RQ7Yh9LW-FoztTir)C zK|1{&igLF|0e=YJyGWu|-17zu7+@pb8*Ps~^R%6P?m5;}?qr*E>uO&p65gQ){Muen zupXNJ{Za2&pT0Z0Dw~>1Yv*G(Q{QkqyzHf zJt8G85d$<=;z=hcdXM{f6kx0buv2A;-u=hzx7qJcKFM8G37`C;+UT@X{$Nl1>nTUp zAAInEl`fMPMYe1T6w{&%CLrkDbn*dUeb1=|QAE8#mr|kP&5x z-1d+Ny#LV{yWz&aD@^d0aur;pNQJb&NxIXDy?%S7}lxOvI-~S+Iu44 z1h0WKexW_G^IElWqzyk`1Oq7I(^4z5yp8j1v@GsVlY!{&L-w&S6;P$zx;~b|Jaju#3`rQE_?26+xOqo_TK;3cHaM;X)nGu z!a8iw&K~*K(^i;~V;#HplzzB{_1rXJkMO zI0j_Hx0qMVA3Olqjr+<%$#%1Id-s~AzCADl|Y&D#;7t|%;$-JIK^=bzu6bUy)$A2)L*E_KQLH$KP)X= z?)FcM<}XfI{);0iky^k-8C8`BbPz)c&ajEWnmu=}#w)vu`Vb`t8lyKSbp#1(UuBM7 z9a}HPO*#aXv4|}g>I3qqE&u=IdVeN6A;MdyE2T)zucF_~zc9DL`7_!Tw0G~`Mr@8q zvO%z<`?y~bG*$^fGZnVGQqmCgDo|$4db?HWWK}E&zhuOa_+29M4?qXUfkp_|*uddQ z=~yv10@2K#Jv%feE+!+CK2|zQ>20O87FP1_t5o4B{koESFTFm(rcaq{8*9azA(u5_ z>{TZHDsMH!kI;pT1f8?0)(rLyfj*Qczz^Cvj|JzQ_uOSW@7B+awsIw6Zr-A)kb84` zLNNm#|JO72u7chykU^NxGTGR`fxBA|5t`Q8T6bS<9MVCndnQvm#hYIued)g?ipFYv z^hcv@($w$losY)Z`=5-{%9G$a+Dt>49DKwPw!WT6w2jLb?fK7p?-gRq5KU@lljRoJ zL4*-~rip)?BIugs|;pQU1Z0(bl9dX_S-9t|C{cK)30AY*F$E?z%GPkg~;Pp$UEp> z@r*!1fY=oS!l_fI+AX)-;{M9?18x6XMMC^~`~>T*=zzE0daKV(tVpdNVU0|AN3_h5^muWhZPC4#b&l+1EPCrem?BN=>6hNBo)kJVyf3s{IBw^1Tnejk-}UG5UtMkSkZKRmLIkSGy%DR;`lQsQk3e$SO494zz{9olnf4Ba-dmQ~;cJ1fB z@%YrQ&Im)K_AdOGr&@XZwat%CV%xeXzIAM?m@@2aewrD7-t zQT0q10RfXYc?_37*8nG!Cm@}R)JE4|f4viN2t0sT9tHqu8{$Zgl%F{X(Pu>jfX#v4XApXo}+&yvYWz`MA|G)qHKR5UtK76?6`^P{2(XPGnDtl%0`!??L z&ulA63QELau=8M+II)B|VL}D4O#4W5+@PaWRcU4+imPTAQ7WXQtXKMM~sj{W9YG$lOL^x-+L>M z!<6K2n*j9x0Aq@AQr#6cfva%OV+_M^*7n>ADlpopSFc`)Lf7G6=osE^|NQ4ay-wj% zs^2HNcS?{DgzL%2x?})kWrcTBlNJ&KLQM12*tqd+s$(}DH`cM2j`=*NR4LHObao67 zIbqb`qBt7*V_kqfgEvQ68f z=cYDk%D37XZxb6ib(YPP_`31}mo0pc{M~U9w;!z#vR+c3-fM=lgUen6o zGxtBq%v!wcE1#;ZGbgYjcz^rb-`vQkt;FwG^JDPDymI3{eT;b(RBqwhNZnw-d5#z! z%+s(v>EOYG%jYZ%dH^h$d-UkxLBEKq#+ewE*$ zT%8d8PHt{VA$T6*Pv0$GvQT|4=~LZyL!xXc{4EuugPZSM1^Q}O~D05iY1}1~W?nx(|p3Vok z4LtX(Pta%{SX~Qt8NCKn)O^{MZ z3^{PO{xchg*_y+kY3ZzQq0=Ffj|i}yhiVgI10c8LN+71giC2q02cH*5mL ze8YGW(LQ=v<_pGri0jeuGcUtjkJp83sOeI z2bW%YiT(N7YizQlGJn4LMw|8X9PJ>;*e&zj7mLLJG!aA9M&kbEIv*pe?1!ItQqq`2 z(59n)cdVUr;rX_?n8-q@TS`@z@&yCko@zHFJs0p0fd)$03qUL8h6ETkS^gb9?s(YlYM5Tp>!Q9srLfr#Rgh{1N*vt@oi*|{@ zWStZB_O{ryDo@j805(&u2Py5T1RGVY0T8XM^_pb;ojSP>HF{EfsX+pJ?6HTh)`&OG zDuGo7h=2hB2gh@>X3cVOKO!AE5*MN?ue{PlwfpR|kFOFi@~a9MOr*dlFz661?z-!) z*1v!M_^X5U<6Na1;uqKQ^TirEA4{b@xKMcD<=0-defHl^RRUqHO86RAJ+(Ggd5ab< zw%yfFkH7MweLVgv+e&)kw_beN?v9B6<4- zLZ?@?WX8xGwqgt-fDg29l#?@O%@;;RVE1MN=7{+5!=9;ZmX`X0b~Zpnj_oWMcu$5%UN0rlzx*vu1`@RN)!{vhur>c4vGr zX5xgNYY;%ByL`Ku)HD!5t~1_J0o?KqIN$((2bB`5Xo!DZ06S%36XTnh)$ju>PN_TX zLA$*3-a9T08#!{M&zFcv`cTKK^{MBo`?=~e07LZwh~WvTeu$L;B6_T5F&4s#6P+L2 z9EC?;=zglIBo(D&g5EHEgKOL);Q|szDxqN*415cn;dF7kAPV$`H{N(-$Y!-8`NZ?$ z0rJ610D~r097Mf};CdZLDk1J#SKu$Q2O69w9R0y3pD9?#GWYQnjZ#BshP(eSXtN<9 zn&6a)qOe*k);2PdUpDK!iG0enQOx`mcI^$<%L={7I*Xxv{Kp+d}m@<5sggCG2{ z149s=3&$|O!*5guJPX4QbAU>rTekw)Y0R-R&p6ZCYHtQMEy5DNSj2dd)B-O&_q^~* zna}4v2JLN`VibHRX#PuCpuMs)6w5!;mPrlML`Ht8k(5v(9ifKG3+Sj&!0XA_ka5bw zWTi60Z`b=D4E+k{FR)KP`Zyu}FB8k7qWbuh8X#4chj;>1u|#8ik;d*&8MwVA?+N-* zkkGfJU%U78s)BPQeDNcq<~CiN6Y>`(5dz+=TQ|qqK@6ViC!qz573@sF?=Bh9%W*~{ z)x4^D4h9f)^8WkpFXmtB)R+XKs`o0p2UEW%*Qg zJyiyvn?CfYKGcT-(HWso6b8af#X)Eo;<0*WlEbyrY1M&>8Z3S-nP7+CGyp4pTp+?A z!7u{J0wP4p%QKO}>O>e#o1mR~xy9m*dA!HgQgJ09$!S z*io5)7r{phB@JSW8Bsmu09#wsqD=)T+h}}dPTUk zU7#o6*~1S%+zB0vLzqn%0LI+aQs;$!jMIcQe8a~iuBwd5%P+s&9}n+`{MM95s`pvs zGB42o2kBL+@A6!nu?h2zHaY(ICp4DLY|?^}PIZYt`PUR!9bf~%o&e~1U_t`%uTCQ|Fc58$59hqA zHbB*JdriyOc-|K=Ew-DWVWlEA=*!vJj4-$*^gPt8v4I!{pR{5EFlO3UtLL!F`ckR@ zh(Cbs7Q5)x3D7K+rD}e#OylZz#~o+eN`*myo2TV|NT^&V{w}hpW`=d}c*OkrUIxqu zM5n0Y=m&^D03k+w2E6_D+kUL*4+{iv2odRm9RRAkfRHPCC;1w9=VirCfT18SY!ZMc zo_NB=#LQKYFHAs15FZvk%=J(>R`h&T*Rtf!833lOsccMIG?kuRs))t{dFn5W|JsOv z3z11BBBqYMT)$AgKi&2C1f@L~M3@T%PzF4t^qoTOL;IjuI~4c8qf{^3vJYCJMFYnGV%XLw|7=@ z;?J|`LVPYH=aH`qU#sDt(s31K$%!YP=$419kcqPoM~|g0u04UsQi)KJ@AD}RIvvTcX~H3^By6;H9p8sOCZuvMR% z#jFA+pK^+bVWd)RBn%j<5&%XYgvv@R%m?m~m@}x%K-Bm^LzpW9G0}b*$pLCM7>G+R zy|ki7tGpJ}06YXk63Rmv_%>stu5`Tdf@PvFi_i)PyScnR+9;H;3Zcgsa}5W~-3&4I zQzfSVR%+3LE?p9ZiTc3xQE{9aPx_ zI>V?iR`)w}YfGh%d8VdN8AaSd8NaU7ElgNGgct(-2Cg}*tO3Lw6pjWag^9?$SfTk@ zui#~giC>wVl_90d3Pv8(0kJ2lg;?Dl)jNshPGv8z71yQ1E-Kne$_>|7v1)!ut0>~+ zD^6Cz&$rwSs&P~(^a)2+%9_mdgS6T|UwJ=}t5axEy z&vWh8TW+rO@%p|&JF_~6$fHtYKCqgK1NR~5sM}brfcQwfn+)iTVG>x`uyW@)R+6bA z%fO6~?|=aVoH)Rg@IGb3E$tR7R1K4IbKR-Y1eLF(^F;v`q^UdQ@mN_avo^_`vRm@$dQNfBv z=;0!CA1beIChU@<&`yMmZkHGq@LgBXai z2BZ{@6_t(WLgGGo5gCr}h5G99pOxHjg=f}Ah;~maq+S?FX&)1N;`wK7-kjOiQhSD@ z;Z8tB!=zzq>`0aVQJ-K;x8%DS+8uBYH|F|CoN~hQZe`ghISfunEAKRtGu6cfz#t!l z002M$Nkl0t~2 zGlf4TQnA_czG|mE4w{R}$y7MZsLe-*wy&rhv1^;_n-lcxps;WR_b^uW-g|E^4`V8h z*YS0yoEVO$1A(BX^KL5dgmJ|YMil869sqndUXRN13h#5Dx|4`^fs{Si+UeG-dX5$M z%RE<`kc`%v6r4%M20FOvz=3f+r9o4RB@7+N3WNQ|aX~`&$Hb?6slo~cUt!Rt z3#@LEbx3LpIN6|rPB-fYdym1V5VlJQV+&k&!?pI444E$c(`6ptKDUK*nT;5*Kgy7m zb8AKZ+q`=>oAmWJF7gaTE^-6Ix<~xsdo?|Fml_S*83F~}C0%G7In*@on!L}Phwww> zga1GIF*msvPZ(|y@aMeq&ht-Fhj?O3;4TtH5b?}rRYcIrdq9KK!I5sw)*oSHLduJu4HEf19p z;c?n9v{_~E`t_*){8#H<=PJwE05>UTpo>VfC^Pi~QlU@rJ|KwDnc8oJP{rg)5{y^E z^9~6>twS;eeJlE?7yb~%#D4sV$6e<`0D@F1RO=;-GGsClyBWhgtc=5EBB^|jPU87^ zW2f?7cm~dnJg&I>3fFUn>nalw4q0yOq;#v&!_n_UbzCbzoV`4S5@NnBw%XG6)21l* zKk*;?`G;9r!4M!NsT$xrlDi15DjrOFvR;0&vR7g3kb{N_$^B@{7ilvZjcPVF$_=`J zdMQcmd<2gb_9Z~gHa+2DRXZ8iAQz(h5#0==jaLkFp)%NhyX}3hA>v0}m<-H8^!FG5 zVl0)PpI`n+D)Te`3=9C0x%grrAYZ%^!g=`z>fnU94)B?jYr%pAVs7%StyE}8D2q#^ zqG~|!mAja+QSZF%tI1|!OiC2U2gZ4o4W`ymMrcBoBt6TuiPbD^x`t?;4RvHd42)Bn z?Ppd0c~ZAqKtt%SqmDYtUeTso5dS!%6sIx7dSR?#5Xb_ss&QBKr|b7F^n&sRT3XfD zQEvd$?W(J;Di7%!waEzGN(9vKr)vLCoB?=4*}H6y!Hgjt7X1{2-$C?N`$ecaM;a1f zWrT|bqQd~G4hWum^wCG{iYu-NucmzD-5eQZF)(QZ@(C86kxjvo%IpKB)09w-9fkZc6X-rZR2oOMC{eETnZ-Z-XhY?9 zi+tztM<4ORWv*%k*fUQwPET?=y`KHKvOD@*bwXv}!+5DD<@x&&3# zVf@4i_P+4bG7*5LGL%C_)ga);qfv}Y_0vLaO+9eH?(* zLWhFyKKV2jpsdga%1MAaJW*giDQ|gb=_(2fGlet^!&(>sfN`w(FkX4!L!aOf{7&uv zQNS#p9Ea&Rkcq=@Ch+6(M~*}E0Kh;$zg+xMot(#Y`wSMu_N)|eKYIGFUW)Qh6GkJ@<+~4AcJn&fMvrr&9$rE zD20L7u5&8a3ReL%WC7FowvaPMRzvpMTag97v%lZ)Hz5-BmBwtur=^i;^ss)VL~RDh9rq=SU2S3st{Gh1RycTrb5` z%%8g;ly_=4;YeS`lg7y{ATPAj3W034jky?FsOrLk2H!? z>IOi}v4LS95XK=4PH2mGLAl4g8Z~N^+teTK8i*}>i3gr8oS+~p1S$fV5vmd3 zTj|u1_~N*%gaIA$;22U=&XaX~U1^)>ccVIhtTc4nu(f8Z*3A?}t&PnW*L{QxZodBZ zdwcVpQPxaS014m3mTK~5#*uV_fpAqogVjo95aP|$#L<$}4wd?1{1=~DZbVE%zcg6! z()ciC#=GIAS6^{v_nh<2^^n)ZWFT~FeE`TNv>mH|!l+ch&Vi^%fY5=gkdBwD zB<%-8&+ehq&y-LPG&(5Du^me^le=!#)1%UX%+5OJZ27XTXMeilaz|v+frvYm!Ve~( zv4O^|x3dt^3BNl=6Y5KwtXKx(qa7(Xw&Jd-Jj4aS;u>QAs`h7StKcmlig(_UWJAnw zeE{u=_>xsK#G2m({=q7FO~9N&H$Py&0DqKKIP)Xf0GGKK2zE42)|7Rn_wgdYa0(zV zTz1hL<5hrImG5x9rr)Wk0HX7rFLZVCmjgaTeY@X& z`<3_mn(+BZEks!rIj|KQ7N6kN@>+1 zQ=RZ@-eiKZdl8&|D0C=bS~;ir5-S86gl`k~o2Y&S9HLC2p{kQL`9btSOdtjj54ypg zJ$u?u+Do2673y1^d|@guW&+UtP)?)__)0(Y&_flK^k(V!& zie&VMW2FA+W1TnM%uYG!WScPYJE>oOuwsZ?$zw3^?L(UE6tpH(SauV59gbjY9m+mAl`WMC(CN@O!3w<6IW;_=M z`V>Ptq)&KxB-;wapKa{tEHrPr=_U{8gIXQ69<-LZ5w*i78k<+@_d%*lZ>3ctEY)@W zGSxW>^PK4u6ANFswa`K75Zsy;I6f#KsKgHUtwyyXNf)R`U@Wk2VD*mpF}`YG&{YJq zMLY$B6U3st^Ugc(xX~m?hK?OJbeQ{tBHrZN;e9>&pwjug(?~#(H>`!i{#$G95;kM{ zciJ*kQOuSsvlEUz&N{Ex+DQ~ zc>@fyNncHro3pH)T@E1RFWG2F4PM?g6(AbsA>P4m1Nz(HhaK))8V}OAb&r&KXm^NO z@TZ5NW&WfJjCu6(=t7w%AVJ#yix{u1`0j0P?o!9Cg%4}1& z-<3VkwhGYFTGqWAvXP0zRXH*c8Zu~48!=|AeJ}skJTVAm5>KOBOh9Vw6`roMqa!?# zdKkoIg|_XMTiFDK;|yZMI{R*YWvpu5KYY0TPP^?bS-wonttRvRkvu4fomA0#KQc#)HR^8+Iz&yItvv8Tsky|Wbbkz`!qx?A+ z{iiU0HNKedKHg;OKwzPb@;9+&Efet?q9L)0f4b<$CHjU|5%3I|&g3Bl0^g!$8 zQeOZD0AL(7G;Q*NB>f3Q8>vqK#@<$2ZDpq@tT*E?R`&UN2Ih!LU8MAoQiB3x_ft9w zCLlC=LzakD0Y-YyJo8Lq0#~v!Pq&Pr!}tb+lEI0aOtOx$s{GO6;AVt=Gwc%(I8@#P z0Wnz7O|m^PwgE21&>)WBXdTh_v<>d4}xi7d1C8ML=$sd!uW>IpWJ6?2hYe9n2! zrTqDtYxGbvH+EWeZ-5k#NL^P9B`ix3HV0a|#CGVtoz0b7;71>Sq*YlXC|^zMuQ9{? zyiZKP-h=kC*WY;EPCexho@-qh1u{q2kcDH|;D--ZCMAnk5j?_scnQG7Q}(buF!w?} z=tPmm)h6us>-}6E$M?gcCgjgtg|GnJC)EaE1W2veIg@WLRir&c@0t2mh89)j(lQnp zq}qn0Y9Jvh7W0;^)%ujFQ#?Xuj~=2oNM52PJH~{`LI1=Q+Ily^bI-K})!~YHSq$HG;`V!TUO@XLO zi~+b=_q*%)lk{l4>G;>wLMl_{jL_)l8ygyEP&n2*?zqDv{?*pXKh%qr38EN8^;jt* z9_-MeL(1IcbI(0zx7~J|cQz{|R!R(RkRxU17-t6fF46+5p@}9KgUxk5TB#wKfIhhr zq33VBi3gtniT!HV-Pz{LmMY*!>#kjG&)s&gC!T(u87L`03n4ouq!JUemXK(yO{#wy zl>rGrk@~fhLY}s0*4$ow>1F9CD^}}N|050eh8tf-pC@E0y7>F=yU+f4tNf^u1k?dA zKTy39(T{CS!4E(xb1@)k<^%+ucd?IQZh#;mLZind_K{CD@?TX|j1v~h%O+sVKjt@p z#|}0+7&r6%IK- zAo}WyRlERFC>w1AGv~Wg>iLOUnUDEUXiNF2Ij8E<*jP4qtG`{O!+V5~r#~1I^nVyf zvFBGiGL_+})>6u=7gk7CF@@zdrN1=&9S{K-E{dTo4#*VXjbLUy} zCQXGXWZIjPXOd^yZ6Y*Fg+(zA$>NNlI?PgJN2w+$tYRuEy{_)T9xmufrfHB5OnRw(#Zek~bh(O&@!43-ZnMq0^{_I{?Hq#t z01PE~I#LSL0~|&ub)+_%_1e@rDinJ&^=p=@8T&do?6=;>5umK$^~!)>C%ZH#^a7Vu3A+F zF|vsYbqnDyqg6^bW%QMjdt+29)0#cpU$3`hVuLW>5z;4kUi-G%-$;X67*y6Fi)_P! zeA~HqPkUGquD<Qwj45~4H z!&t;O7E3k%H9f~ZAt7D}<$!4MJpfl?)P1!HXrKTX&E^WV%c2666rpqL52A0e=FphW z5fi^$UNK*O{k2q&icKJ?gs=RW3t>LQ&#NdX-W%C6u3a#HksD6Kyv>_4*Gi-!6gv@L z{d-G|dY#tnN7K!4aU3WzVH${%jP6Bc?%e2AV(_-;H;qI#m| z-(Ly+)}&CxKu5yw#&Qg!^iS~uq1O(^cXeIxhzL4?#c~+;JbZW?3xvT-XCwOGamO9) zPHof@Ryu1cCo7%+yu)T8W5>*3fHvZ;7wt^%1LomJO@e9M%} zU#X0T%_?yYcccpTW>Z6I=9liyu|8(z(A=)6RU^HP@qgP0;STyZngOq zHur}g?MJyVu4{nUzoR5EBVKuxjht-Iph5P*2MI&$+L)^#UbZ3~Dq}t29S8-g1*Cj@i?RflLv}L+QHPMSVQyEI-TW;xt89gk(^;F8oGYlG@Cj~&#f}2PZ{87LE znslwMewLf%Znnkdz71_}EOmt>FeFkZDBwqqEzqVdJ8BizcgHQY@ygTo;G=AdV< zX-QymLEzY{FbC5G#yv~`DldR|0sz+`#CR9f1wbe;zD249F!!iOSZE+p#&SQExtmJ) z!ft?&Rv3?j1b~p>G75z7*C&W5}*>tya%(1+KVZ2Ac#|w`!l8(2Pd@aBqJWj! zDQBE!nVmZ-@U?7xP=Kyl_BtkM@9_C3;j&jm#7@QRxc`CSRw!?t9k<&-48XDkBODm^*gI=t0y2HK)HE_BPm@t z{q)oAFMs)qTe!v;fislfd+Fwx!h6C@){o~lQiL#ep2LD37dn$}Sru}h-%N!7MpRg+ zD1j|HcCvGRf2_SS>V2C$Zmea>5N$a=t}p?O1SpB?I-BI$w%TU&5hsqJe-x3dB(W-N zB*jg?7#epPeE$9sM;zfnRuG+{vkyCpakDz(l9d;sf7#QV)eY9yAj6tMewTa?ki%+; z{FpOr^1^wD4jAT8b;?^=xyXZW0elO<-T=G>v&4METc9?+<(Wr9lDT4@zWL^B5iBi= zg*SZVoF+5o`KIzm)#LM?bdFfw-E=iC|Eq|n^d4Iim#Q3Y3lq>3%|ddBDiD4q9ZQi~ zYEz?evi@(^x`q9`02Q}D@9R!N_hfc*;$p%mnkbAwc3?Qd%@mIG8N@cIpP&g#CBfi& zz`ZGCllCKg2MGja2t=N-^4Q~#d70SA2=H>2lw79M&6MgASM#|#gNm>>Ou#`(c#!x+ z!B-wp-es3v=JBe203FufK(+u1 zWi0FGVxg;Yi~3slY@^5`nun~eFTVIL%5$u|UVr^{AKQe`WlX~e z*Azh7_(cQEA-;upm*{Xv#OeYF`V;0P$lRkR>buw&CAs3(`17SvJlw@nJ-H7)1e3WT zhB|m5)c7M+WDtlxM@V^|w%T2yI2dEUo@85fFR+%aTgqTB5tn4uY~pQSITMg6v4625 zfR2&}Q_FU36CP9=E1LLAvvRV>M0pMfd7~G{euREbhhWohyoa$N3nKOps0~Imly6PP zK>R5K=NOUV`E~5E$I7N+iodQhexmvfR{5@6Q+|#8etZ(a0Khk2my>&KwSWHmT}9sn8!!}aKVK@a}5Z`ntmUhJF4}Z%xv3O@kBQ5)>Waj`MwAl z#Gn zq#TolA2eQs7K#gt5eKwWf>t;b6cl*d(!PwVbbv9_t5+}YL;A0!RFdQsaBn(!R_7gT zM1XPQ#<`&%d(!Z2k|b@9sVv*8T(36PxCGUyYdImP;H9yu=+3%+eY_)Ct+SOUBEl=K zyrNv(7Vn_y=zbu8@s$PxC!Q)OSDjy?E?8D0`X`tPE`OOKaLMJ0w@YP(ioa9QdHg-} zO9ajc5Vgzh`khc}h8s0FGH6wf?jaV!2GU#pID3{2*>f+;ZP`LNBx33`*xkavSOI|K z`=6nePVvmyHuQi4Y?C(4?7WLF($>LqGrY6s$r+mI<66L{b6rhKC@x6C%$puLr?SgH}nJO~4`w!a$X$9UHu<O{(n)T%z4`9j zJ|+6^A|ay2Lbl3LifT`7;gI6|r1Y5z`}^6%@wQ;mQn{W=<%fh#P*!Y{{X~0K(XO;V zTP_nEEfDH-`jdRf4Qd_#)LkoF;&$))U!OPE&d-@b^AjMBDMdXzGOT&O(Ondlqwbmc(QP^%bH_>HyX z59Mb7B9#D;Oz;~-TURTVc++5TcW7R*~uNtsN!8luM)(+{CgR) z*#8;}eHrgd0#PWB9x-x02ZY0_4PpSMe?P+_*1=zoX82Y7(AYaJs5)?wCdLWlFmn)DJ6(P?8e%Dnku&b zTopY+>DOwgm+9c3ug0$yt`DOPIBmiSv*lsXrL1iY1ma-#GZ59$M;~n)b>7IUzyPTa zkq_TM)k1WsBn14b3bI>G+mnf-{_D)7?a{NFM*#eE%xAXUR$C@k3CUtYC;o|H0#YlM zk=VfsdAaj8J?yeeud)SFA2e^>$~O(sI#d{;rX{S#`xShPu?gc+v~ZE_yVqdL(+cf{ zXaA!}W^oi&zs0OZjcW8Lbq}j2_R`?|!V52SUuEur>?#Aq^NbDlYX^9iF<(<4PnduK z0|vMb6`d*pv5>6Q780j!7ScP^nw-fU_aWm9wrWM3CN zq3~WHs1G)80rZ{Mlqkrj;o7=%tfJ>DtmX?M9Q&x@56}i5tV$i|2s#9j<99yqt zQ`@k8J6pDJK|+Kca*9^|;is=^2m>r1`|JO5Eejp{+l_y>%#IscsSpg&=~jbPkj-j$ zYkmRb7eMFyL{d?r2!|OmfZ9Q^4PJZkCD+j=Zw{1rHoUxU93h0HZMNQ~Tm`^bVs%py z!G%}?sP+K%;RuMeHpV-60U#nE`66jxbC_1GT2)vcf4CZd$e%<#U@lPCQBOq3qehJ? zCq~TUP?lbzk>X zd2w}V;4d*%@4owv^ABNlt{Fxpnb~j@ooR2{770KAu7%ZlxR%N>KIS0E{Kji!v&}d2 z2(?(@htSeN@{mftl|92AEf9Y;hl@iruKuoT2@BTv&2{L!$`Mh;gn3Sr`4F{(EUi3@ zZ8_2i$b*>NFaco@1mwegQus|k~qGLOJ0!narp)5T_%Y@3mfLncYc4Uq>n>SI zlqWI)$s`a>cD9g=+Go4oJJLCHnie zQl8p(1FnFxh)NlUuy~4JOXZyY1hBdf=P&`MopzdUxYNIXf7@xNojgtr;n~@{f)tq9 zioOx@NxnC5;J{VJd6++X?rf!XPUN3lf7Lf&&g5H(-<367>}jM!zfnSVcz{w<5DD)w z`SA%Qv@pKKT;qFwPn;>@p5*T*|5ko=4xwB`{6m$|wQE<8dw@D1jzH?XAeDRoHxw*U zDQ5(y>G;p^qdG^`X9wy3KcsKY{l7Eq{Sj~2(Zde36OTR03V-@RB6A_9Ql+r^55t2` z`?(Cp3YS_-?YdW%mu=0uDCT#cZR~~D|7*)9OtM@d8L=;Vw!Ey-d(|mrHJ*)^&tFs7 z1!Xc}&d?Ud#o0}5$f1YWB{%-n`tH$Ro(>6uCzR#SHTa)cGo@9QQ2$C^W(*U0m*6-c zNFq?eScWmrYXs)ODxbNBI25}c5IWCeO^PNz_ki7B68#Z9TfNC=V zlqoPRp0}ac)zRCWbi%hAB;#tpI1@pN^dbv z!q~$Y@0&^A*k_-9=G$O1HnH(Q-4eb*|MCuH0KnHUxY(T#nXyx+PHqQ+Jpn2T0F?&J zAwi*@eHMo|bMG0{M-g*;zb+l;H|qEg^=L?_dUmH)GU81jnkIEpdQTI)3mrmw{`u#9 zLc#!Ca>*qwVx-b=hjd&+LmbJmdlduV4}Tz{BNDSnXV$=l#J3yk?iie@^RyTMy|-hS zWM7W^!kTH-zvqBo$%0wP9^zlsc;uc|mMxpNuto9!XxX!eU4QvS_Q%VwvG-qmS;3Na zvEo^?V`>EYS9#V2B;zxF$I349@9vA)`5Rk@_Uqff)qef=+OsZ7(x~%Or!R zHjEklAu;-GbM*hAED(R)!x+$^GG>6A!g+WMu>CK408E-Z*$AK9y=%Tr6JxV%xl4~i z#|`Ec`U7K2AP{E%k;WfvHK+I@L@Pv*N>qiYpb3!mC;}|?jjnO6c7u# zzX1aVxO)Yh7r_07hTt#EK*HZ2E7oI=J=Tkrt_Z6(>jXnmP*C9F+*rOnbe@)YN)uu| z20g315>1A0CVXLC6%DX#*-}l4usUY-Lef{_iPefG81d+HHB09y*vM(;o+sC*)^@;Q zM~dJscW(ez5bF4q@5TyVFQ@u6kbx9JAxsb0e;*qyKk(w^+T`dL1|UAhF}iVVTR?)3 zKKiI3MkVYot0@?Bp5s3A74a%YsI^H*LAnI`V(f9ApP!#rPf#YJ6|z~`HnQ(PGz`(7 zHg%eveDcX&X6jI10P#mV)?9WmoA>DDpXK`y=K6pPtz>aUq)oMYvG+!QV9er{vfj7l zOGNjhwg{32wO^H>``&(%&RUbEHdU^hQ)m2W-^&Gf$;$b|$_U!wQPOyxkm5j1$4oNL z4Sh+zj9qNBaF^a;`yE`>LrfYh_dojRBbQ#G`XLbv3W)*6uo$>L@W2CZT+O(L4iSh7 zV6lhV3&tQ;b~WZN12TQEGGHr7X*9zG5%$gX-dRd7@_y(<&PR+GVFw*_kh>@?R*ZQX zofJAC=;D1q^THZ{=hyUX$TM(<@hn5V3B&_nfsg12SW~|KP#ynaz|%f=-F25oGUIcR zJJSt1^$A#25tyZ<7$giEG{L7#{>J($5Rjbwt%MDLSS752JCo*tkT=Ww3^@Vk=-Fm4 z409LQy|>+Akk;FW-)|Y4Y-GjauB|D8M`fmQRUV_%v0^AuIL1m=om0vgFKhX^$_$PZ z0|W9a{CSogbifcXCkt)lYlQJke76{c*%-jfs)D3@tVSIe+eGt(2xB0JaUhW{Wzg%Y zx+~<~$^1kGhQ1Z`9b!@D2w{R5hn&ZcseYbs4jD4U1`ZtPtFN%XNb>t}ToL9b&u|XD zfJy0~fIHYTkRJwNH{X17xv?(Kf=lB0aILPu7u8~lOBE<(p<*wU5P=_vn&uoeT0^nn_=kk1dG$YU7M~5St6CP)?IPE5^=G z^Jh_s;z8s{td7O6AfW^(nm)$V1ONU)KPBK%}Ss2^wUrK_U^adnlPy%I%Qa}s_#Ce|56!4;kk5= z@iI5Wd7=et|I0I!B^F261#F@8w2}i{9E25*0rWGhHb6SWdj^^;|&8N00d;qF&zdOri1qg3RD$PCdMga zmS8Nb_;EdE-wZqoh+0U(@;qJ^@CCYK-X+yFKwq)3Shi@fZ6T=|60&j#tM2j(wSST= zW;;Vs2ql8B$x=hGG(Y!T*{{hxp;+7ZRvV%=^OjRPemiZ3@BD{lK#W*SQ@%Ws!=49- z)7!Rdw{nx9YJar;UI=3Xn+5P`_#O7TiAu7d{z}xaUyAil>84LP=2z2uaD6$*O; z{Qj6@qbO!vm4Tb<|3H_&EMPpbD#FtRgFvFU5&Q?^IoH2N&B020qV|A4{`lh^Q4*S! z_pn8QcrzY>ROVikr5{+C@lFuI#_w?+T+LwC(d`p;6tx^>ZLMu?(bM9mjk__1T!Hw9 zxq9PGH`<`R2Dua^(O4d@a(&wnWow9U zigm0vct&3$?W2i%h={+Ip4Nm$C*g-oI`YUPy+Cvf8%toF%-~~>X+)Dei|+4${SUCY zGDJh%$I1Y)eLw=9LDC=Mj|1cv2Ua^EG*&<`Awfz&JZPCQ#vg64bJ~KzO4(Swfv~Y; zjRx$ED%iG_7A_EO5J83w$STWd4)LRAZCkarRx;=-TsY72;P2J8<j`qRCB9s^ z*oGZA)E<5MS^M<8cdhp>yZgisK}YJTD2?Vbj2nn2-T>?-2;ssOCe8rx4EqXT7emBP zM5WjT;Km2QFu;s5U-R?xy**Q@AQA?|_elQuMl!K{>E)N)fa|4~Uh;^BjC&F)y8G_C zPrKW#oWC$30ipA4m=+`i7DF59$|U1Uty9z#6lZbbVjg9$3|X@P}G_qYcMow{P8Zz;e4fbO1+g5 z7Bo7k3ebNe0!K87UXspZHGvgyJBgvtXL29lSr8jyPWC!ywS)CBKF{b4kwCor?z=W? z)+`Sq5{Q3%kW^KchPX%BSd|g4fbxRm1jj4gw_17V-O$6h^_AJVa^t_gL=zeY;J8B$ zwL5RS*@~u2vTVir$L?NKnP~JjQ>iTwUkTXCbnt!ZnjYV_cLcsGgD~c zGVP6?;ik$m2$fW2HKH4L7hLTdwQxahPRrCrO}iJ^A#!J0o|SFSz40a$_5BOf9=~W{ z4!{gBj$pJouL@pymW9Lw5a{W#I&9-VWM-&i z9x8xWUwzGfwa38da^pRKKjQ!cibRRUX2gtss{7l;pQ-9RIlro&ZH)KoQv#4&e^CfK zHM)pTDa=48r9n#Fl`4eb)&bE5VUbwD^BbtDLtqwI)quD_cqE=jFByQ}$*YoZuQ41c z8&=Q5hY$Cu~n=DJeTY}q#~SY(GE z`dd3g7VnD{@vud!HX1=eyI8hLgQd^`b|6G+$q=0!4r4b>Ptc(CoY*Ipi# z4be9SRk##B_~3&+9s`5U^TE}MbC`4_S1{wuLl|}DE)eD$5;$UBAYEYlaTo~3W?Ztz zv!QJ0``;S%md^(meagcg2te|Cez6YzWXT7gy70X`7^x)-{VVY@*TH8!OZe*MZQI$8 z64T#t*F8S3H}4_TskjcT)?KY9;#?h|eeo(#QSA_RPZeIqp#wCRG2XZZd9sXgT*si3(rGmHgwTpFRxa@0Ur;7?Uni| z!64kL^p?^XrNRgS6vGGv1fuKSsi9-zVnObKhytMdM0_5Q2%U~7l;0o}@^8$*3JCEj z8wOGK2=>zPi11^TBh^V%2_~y=wpL>zhqhjeHr8kR9j$25lEmZ4GFRr8xK`!g=-aX# z$kIwDOKoS0zu!m5`?tRtX8#!es7?85oLL)*Bi&Rwd}h_jSLG*a>!u8%3Kz>A@YnlW zN7+$e+y<v)#E@b6ykc&}=NEPD+^Ms>V&US8G!6nhcI;T+ z7z`2qdFP$y#GI8p3;@2`j9EMYAlSGjUVi!I&OEUC$8GDL$_ixt)uO!lex8+r$ z4oiM!ZT#H;2&&i?8V59oR;d+48Dh*_AyjOx{$Vcz zVTJ(vc+fKi1qHU(Aox--;1Hu2z=ZQ`kmkV*kS~e%0nUSZg4HG0`7UC00%Kiq#T6dQ zf;a$OHtABHJLL_l?@*TVn{{xqVBTE&dCrek(66r$OtvT@YA)5msk76^TK;O3r{++J zn2b!RUtU)j+&ulh`cGF#q9^qyDp2NJI-q_;{envHGwr0=L~7F&@(wEHns9{NXEEyD zP-$1P$DI~KTLMSvuvP*w1DFSlIl%{OWhK%qbX|ekbYcuuK*Gkhx)W>UrKcESJ zkB(RA+E8^M>0k}uUP=WzFVJ<8W~Ut?g!4Bs2aaJ7MFJo@Jr_FPuQm2RAU32Llsg6q z%o)1?ZOtUCuZQ-vJvBj_fX)%f57@1b<+hLuk1TwJeuYgGAxqaW=;0^$%W+sdzvOcs z_52g>NZqb{q!!G{vU_g*hkZ5qd;7;fZ?|kkC0hm&7NU20ug76FN*H}Q)+vy`5LXU_ zZ1#_Ks{Daxee<==`fjQ-Bx~CQsO`3baN`pA)W4o`yBMMZ;*B$K;6OLVi%Ziu2T{6i zTLrOgl} zP*6}_9`YbRj->j47Baxg6mjgct=1fcOEi}PYpan}6a7C1IU$9LD8CZL87Nwz{S|bc z)3S|CoBo~MdHYgWjn zp;%Hp)OUIs1HieVNVK=^II|Y6HTENA4vBFBLmEK8XNU1qUt=hIyCIHAz26W;sIzY} zNKwd<;OZV#x=oCO_Jv7Qn@vO3Mxgxfyz`E4SsW`r205z$wRHN&)iS$M2t~p168^k> zwv!zX237nPu4J&g)v`nYYb5-ue1#uE;BG;v)t-#{ie}HWAu>eTwnx5Qb=`FelCs!x zwfma~->EIp=xSxC-~yHRgx!OP!t$loZJVvFojf0&`}e;pc;T0KDIhrz;wh(`;v#G| z5gIviq#N|1kH=Lvh_=IOJ>F6fdEQS4U_g9juQ44M0`g%cPubX|?UG9`G292)_=Vs^ zAZ)fCZ*b7ODG|Z!(RCBsq+E*b0H6#D`6rbw;upYppbs$) zT^oUM`?EY4fM_mMZ3VkFRZeMrjAp zK=rW5nyuV)W~?vz9uGMa0w( zi76H_4b>~n3NbXi|HZ@!)@h@Stn((Dc>dH%>tuVEW zKpy6S%H4ErDtk@KiqQ6#0NB0#M`>G-9LVaLYpzM?t=7`ovoAKBw@<)?k>tI}RRJY4 zNd?qD2L^!OJqxwIc-#+%2z4x(?#*DT;yY$lo zQ7eUKe}Tuq0I~rVB7ThUkOW|;hpX&kk3D9LIS4d{sEGfE4jt;Qw}|C&|6^bEbb#;i zeIou5f*45vdsPsi3n?A>q8?zpdpVI(>G=i+jj1IXPqarzg(qHJ_Xvt~`?`SiVg`PJ99d44C`W1qpceA;&=Yl-x~0%M`5px83J^2P}L$g%e8t?z1v zQra5^y0q-#_y;;|u%XSLH{Z6^CQ?WX)5Yri}FOzYXLyKS-kwzhQ2RLjPIOgjRUx zrT!o)idk|)MhZ}-G3_=nwF&V(9smG907*naR6+F1?FYj6O_ZsyL@REE*fx#dTdum? zFP?SU84~?##>sHcd08f7G_MnHRrPme{zw)GkIn2|T2yGW=l-N1nv30DM@x0AH89Q%o4 zegpPjxQz?Ag<{OBXrLaX&dh8}FCKh3dRc}r9a z%4y!pw{j#|SSqQ;)EVDdkIgo<1yY%n2xnrnD=V7KW$?GP&m>(t>Gvnv=G}Yw%P+FS zYoy-e0?$;Cy+7O7{#)S1G@hU2|rZtHb4tq~Z24=k{NgJdRT|Q^N zW$0TN2~87{I^_?iTCP@0B~nUcHPK2YG9FCMrq+JP^H;et#FVV~d7d47&;c^s>S*IW z{=`?BAgpAl=vwkKztrD>7-OlAlpxuHKizgAub|pORo7Svf2bd>#6%!<<}qR>!@XKL z21$SuVC5(=e2ewl+cOHuyhQWs%+pVo*1DN?yOir+kuIbSQp3Q!i@8`JqurJ=1l)Y9 zErm5i_W5>MnM4oPNm!=^M5AeLj_oh$UN_BUpr?X7DO}(xRDW%lKP(7IF=kV%qhAjE z5*UENbZ|ge#5N}e00v><+S=6J=bdwoae~hV#jd5mqPWnZ`00J zC|qv|NTV(wFabgzxgx-e=ghTEBDR0~%hmSSzn--x6w|#~`weUnA%v5ei12PW)<*f_ z-;jvEY=y$7N_W{t;bs4F^_8+@MsDFqt{j2MtW8(e1{78s4U~Ew5ar;O7bp6)B|Rbk zpzntnXzWlZDOxKT0?OZ!0aW|N#i$R^k-1Wg&aOps`;P)GF|7C3mdK`^2yHIT$+ zZ3AckJHVoPf=&qDUfb$WlkztH8CH|p>0Nc|_aO_oys+6&*!YA_kEif#V?17^phYuf z=<~o`ciE{Y9Op%hI#3ok$-o`l^U69oA=6LR2Yc?lr!{HcM$)e2e43_z=q#`4XJ}94Z;hBb7$KLXPjzVY}U1y`dqDB}2%%hfPk1 zjqpDvAl~K>c6&twkMH)Z7~zIRklj=(HL7a=V$A(p{AIa$*_~5KhO9}2{aa+ z{Y*aUGQ=OMuQ7|SJrVa>$l&smw?~Oczia&!e5gP{%$Cg-ij(f%0}%N)lg4cMTp-U_ z@@M0JREE5kHg(!;`{wIOHbH@a62spoGqSWy?1qYzEhEB3CrL}hD4bXCl<4F*=pi|nieE_ zznlr6JnDP-QkTiltbe~<>_-`JJ#hbhx{)%*uBAf#FPpW#1vF%q%1AB)-+OI(RT>L< z?RBf^kb+SaV1bW#KDViK{9670`RYGw(V}gg724XCE^!whUGQhiCwiEF(bY8`^t?w1 zkr@B0@!vSQaJ=C!x&W0xYQGqQkY7Ga_Uzlo2KDc6E9U%U%e50|QRy;G_YxcN%B$s{ ziKBq>i;d(YF#4?e*~AJ%)2OaTtBA`RNiplC80$0xK&L8=QTo_Lmtp{3z*t3q;Zmbt zX+(2+_}%x~1!tXQEww`Wo1&oMZ;Zt;RshjFNA@;AX%&D0QoXkh950>Sw~rhmgftvr z0BQ>=nehseBaP zo5-9i6dU97ufEXe$6cDt;u&i0>dL-D_V&5DNU=UPlKW%lb{l#G#2at8KKb!fKHVVC z;9;`I9(%YkIKhmBBjH}&Xpq7*;78YKEC=DEa|N%2Hf9qYIv;hw+5i(j9cL$>a-v*( zO6*SUquzI$ZLRpbX^LsTopjhMWdP!8cTKJj^;g=SV-q2g*0Q|s(y_C4EL*BgK32Y) z{9bMTMtT7gAfF){H-3Vz{%^YZR(s|3*X)7kp0|hZyvuUL1QhxzoxVy8NvGAERs)Hp zQf{O`WnuyxS!*Mt-^(-My|+f%Pf`i^>Z$yDe0-gr9;r0f|DIVx3rw6a(N~b#4o{2# zEO`WRminFp57+6rz|t`|Pv)jIH?mXQTKNd{RqF z6isi%ay#rd2g@(l?BDkfx5MOiLm->N1@o-K2JLOgpn*uV1M~|gv7_Yc8C&=!9-6QR z?X#b)*Ks3>KcY#h_NXzezDS5=DXZe_Tw6k9K&4MK;W~EQz>YfZ1lv{I_iqk9*nWS` z1vYK`x0bhIMf5=1G`(VwZ}0$fEiQxQXu*NSIYwRY_~yY%9=ws^@xyZgrW*5=BqEMeX} z3&(OlJSoK)&6O`z(sADYJ~Uuo!gs9C>bBafN}?5mU+AIbdFLbkN7s&9o-0CPN3t-y zDZINt#R@j^ryp$jy3N+0k-QdF!fo)ELvbUjX$_m5M}ML%9CxY=kXfc*_vxYq`fffV ze-#)B>}nSfY3|pbeq?U=*{Q&=oDkq~M8@`buT;1rk5A zhefCwFd>#lQM=)~Yi#GTC02-tfte80a3x&bzJ*l8XE>Xrx8LgHvIeRxnJhYvb@2>V z)egCUOZ9uj6<0Xi@7Mba8D4d)+j*?sf1+SG&BQ($WKDR5Hua1FkJZ5M?Y$X9s@qJE zkJIX%W@E>VweoP{k3WpA9D|i;EPZ3Kyv~OKqtbphZPM5Z#$r9qPx^&ne^?XM>wwnx zg0^9PVp^VLDrYxrV43*%N(An1(*8&lkcQJMDmVygnBOMY*gALVgz57G~ zj>9~p$8~kWA70tCX_J*ElVY`M)quxDGVtcYD}uQeD5~1qyxB+c(nt(w1uKs~@r+d^ zP*T%o%`AEQHp>TGWtpS7WCHYl2dlJY^#+1F5p8hI`gKl18V2E)DS%x3JKxpWij*j6 z8Og{CaHWj`50O2>Qg&^#G8HP=m6x<8Xb@pZ@9yN<6`2P_>cQVj{k-wBC z7jb%puAPV_%ltXc2VfBWi&GyZ22#QiPXgfW^Fsf{(O-de@6PSJtXi3}Hi|T@#mbhm zt*chTZNtat23fIh-(eS=)6@z?$2wy`wVfayt%E-(E8I>>cq7gFxs4lIjkjn^XgTr zkQFeQOxUOZawUf6F~OsXQyusY#o5PWuS1wR`{dIhwhd`o&Dtjs2LvXWXqM4hmgn|; z-YXm-l!Q>Qs(eDb9KXG7+cpOaS|doXQKf8gyZoZIma$`(#p1G?N?#*sYc#khB|gzI zxc{U6{j5gC()MA$53F6gb~a}0SpQp&-7Xln%LV+GUw(1kUo!aRT0dGg=Ge9F*uOcL zUL5<@9N89Zr}|gCR}2|4#Qy&K?<`C}@MQ7sJCb{!bItBINMF_d`WtKpV#UTp)|yA0 z@fvW}wqdOmQ{HhwqKtvyyfYJ1EG8_*8l8To4+n4>Yx`Qr13bE3i8B?v58S*N5iS#U z;j)AQqzIu~$sB@`P6*3GTIz!LTXk#Gj&rf$F}7pV4%@V5gS9;W0xMss;_juj@E7IW zi<{dMJzlaQqrR~xUh8cIkbXpy>NEpsfG;~46-A)~MLObjZjZgMs@;Es+Tl+6+vJY@ z?NyGr_ucywhg<_8UW%ikL9fH$1y*3mt_R>!#vYznvw9_xtYj-3gBvT7 zHSG0$qog?4+2`MZjGyKuTZUX>sUQKHf&yhL*skqy*89D89o)ngDk$)`7%j`C&N~DU zc1?#b_SIAV~x1+q=e-!@w2xvT<-R z4}5l8{?oiHP>9UoM29*-Yy=*aBa?Gh2;9S!ASsP^T6rpj^R@WX_hXY`_+9>E@7x}H z@A>0(@6m_jwSU?B^@;bvm0I*AxztgDx%%u69Le8qVe9__G9datlG6+uKHRzc4gF}K zg^9xlu^8OGLUalerFWABZg>P%{OAYkopPGPHBqrJ2WB5`u-JMl+41ip!P?)uA z)7qsERrWt-IduVS+8^N(QLKb5UbqDJB6M$LkIPcj48KR>V^|VD`s}mzdfyN2i3cAv z!ZiZy5f~H+%6&*6ECyFW;fvrcON9sjL!p5)Si!Vzd7*Qu8Z~kRL6UfZwonO;K(-O^ zTt&5Cwsa|;q){fK>{4wi8lY#eni~ed|1O_9VW!0pT*!)-vZ3FNvZZU*W0?;_%|gH; zqkLX0df#CvVG`AY7gnrZwMT7INyZ>UytW;%8=quRFaudsbExOS*&={bF)pXqKH0{P z`oXSj)5f_B{)*Sa6Hh#4b!*hJ8l)CJsP z-*)oj;=ntCubg1Vhi3-;cLr@GAAKmzy;e>B>#x6D%f%FE^_|Y_Ioh!SQXMf5w;xA+ zXOEGguqL-Glw3_b%7?o4%p5zt*>4|RjQPZ8|4_EKg zePWm|YT3%l5CABZxcpHbaAaqjy$27|-o+26F13Bg&@bKE=(5W$+oN{Dw`}i(%btDa zS(`H9H+$oq0ak%@#rKgxFl{v!%8GfA0)h~aBd*Ec_dP1h>4Y1soG$p!@#0L?SGb5Z z$Gz$EA)i^>tFPnY{vO;%ouNy|?Fh(H+>-*x2B2Eisz|5&qO60Nm%$^Xspj#U%gdG!i=y8ClhvP3b{qGihTskUX~dMnN|VUh?EUnAFrIs~U$TnGjhESMjt z%E$j^SPbynvS~BB{mwfqe))1o)B`u^K-AaIFDn~i+}ibadaaY~bE1{bo4>#Ye@>*m z70U=MJl(dg+h|+ZX8kkYK^ITLT7*Hwqpe|s23ERk8EbHMBa4TTXxgl)l`UW1rc9dX zQcpK0@X)%|Yg`!js#R+^*S*375lc_;g?UF<;np*=km^>eR^5se$L)B|9J}hOs{;03 za`W>uaGkRB;ROD1qA>tWlCTHaE+sxdei?l|`Q(#M5};rj!4{)OV@`;K%TQ+SzjN&R zYp=1&C5zjS!$(?8xaFkPD>3+El`p~%((y{T42@s{GGSK25WBT%aiP_$RL&NxTIb!u zvcbv%lSKqzqM5B*v;;|EwTt17gH|8!!0{0(PRiiZDW>Bl^x4<7|iWj-EW5P3#;zh;? z;&NFukKJ-M%=zI*;9~grBi&rijIqCtwp(v*Z_Ab~b6&h*1&{>nK&yEOb6>5Lt&JFf zG#HLmD_1$=J!q+0O{*v2obT4 zIHg5ks4xO290Nd~*RhIz9$nDOnz+4t_qOicyC1cczjRQ6AVi4Q=FXpI^-rs3C2>)i zIC_kgE?&$swrphCn+Bk#IR+uiOw}rbc55}9mXu&cNov!qQDa-Q>MN}5;pEdZk@ed; z0gnJh08|w{qHWvm3;qL=a)mkq5am0QyT2m#Djrn&S2F3eKe9|2n>=;8Tm5$j5kzXG z#C5IsGa?b+@lXVQ%qsdTDNIyUtd05Ycf0D+|5?)u+t~EqCs>7Q)hv0%3b=mUj$i_! z9TL(w=w-VRk?J|%;%}$(pQb@cyOOLLSrX4Y^)&1MZeM%i`R5O~s?d!m&Il;rjwFRz zEc`n9XKQ;l-nS6HG>D5lbOI$CJOs|~>p;%{!^yySEGzzLtbPZ7J<6I8^S@EUhE@eQ zSOfzQ4;+{n00r~H$k#`Z_f>Ju*JSi32|zk_JZuwYE`%Mn>M!8 zH7kkvFGBB!cdtsdnL8CT1BV6pgm5P{klNBfHEApW#5}}e&vRz&TGpUG$@X~0#TDjB z*%%mJL6Y(bAJ6!Erme*@N3P3jVf@GcJ`p}=mm}`;=FPK`Fy=Ch)arlXQrb)Bh0(kv zk|YY7Hf^w9fBjXJI~3uhrowk-&DbXDAXI!Ka3V4Q>iH{dPp}o$qDBAAL&cw93ND%iH5K;AN1N{L+>!nzTWVsQ zEa%)Go%9mY$yec2m;tY0 zs>BsF`VO`b@%N2K;IIG71%97M2hXdsnn(i&4rHz>miLh#jxe}wF{3iBIrH>-wh5hB zpI*JJX^WPYxM&HHwMZ_)b*JBR6g~){__)}t--u{|HL6whaqN-~n4QhmK?j1xj<<72 zkexIl@$FIefRjD$*#8ODp-nGy!0$bxu?)AxE0(jOG5cr!e0vb%zRR!tpOqkr;WHTg zC8v=Nm~oJSk2AcZ0@+09IYsUIZR!-#_LjD`H{4(|(R~&|M;IX^C>aZ}s@N0Gy>}nv z9t18%B%QRX&6}T(SaOTq)%mW2tR!^%aXkY5x$THQ^HhPlij$eI!C6QEyuezy8GvAz z0gjaTC#qNx;_=V3rR%rjHB;KD8NxCAt5fG>Cl24XZ7asWB;dhy^>CDM>iKQrAGQJ& zK!N-P0?X;9B>idM{w9mxO2k22hs2!wh&ur7;SRr%UZ5S}s4T<$n?wRqX$WtjK0t(L z(Ig>@C5}M8B<*2#NC*~@#K!q>_DO3t;q|o5l2)M7T(yC8i#sfw=&h0QyQ~E2zvv{q zEr?VY7PsAs5ig{2*-};mkEyaS>l=t+5LAYSWrp9)@6K$s*#@$OO12RYmOfF-TXcM> zbVHLTPqz6%1~5l-KwvZkVI6P11%K3Zdl=)II|xJ*zi2Vsyf1T}V?+>3r^w=eKP3s# z{%Lhivbt3(A@0IJ$#LHRXt<9Lu8Q%W;p;Ac_cUw17`|rQj z=l|ZZ^UrH;ufP7P6^tohBflAe#DI3gq$qM&43_>{U1=2*jt#^rTp%k{t8N#xxyS~7 z{<%fT@P~WT(G!9`e27Rx8jMH}vXhSa1EVD)0RYQ6o#*#okMz}Y2=yLhGeWoL#SsXe zTO6l|kWuC{m$z-%YGp}=BYT__sn&9{`sdk9)MbuHQf~_Sa#{J8s#wm^*cW@f#8NTe>6+yi2QVMx*;z``F| ztM9eQ`yto^LavYkN~9$|IXw7?eum?AD0gPrTnW$Vx8j;e7a@(FVhqU0Ayzt0x$LPH zsSz|TNGQU9&va}EEHU1a6c&9aZbV2H`VSaj>+mMfTYV+GFZ=h|`m-(doeTZVJ_7sr zqSWxSxk{Ha0=D+lM830SPWy7*(P4oCScP z0uWMzvyKL-IG-6ol(%u1>k?>Bwi-}Pgykc8esR~qb&{D^th85ZbyzGapzTk`@x{q2|V(cw^5DlrUxJgbPO9_?oN!A1k$ z?c?$>c+V)Ykz+J?MPTn;4DFA<5%9jVrlpQ4k%A+L(W>PutvqwO5bml;FpiNhrIK7Z zAQT{a&pM(hh|IpJHm0r!nur^#C6wMh(^Z%I%%udThGUz!BzNTWeO*0nAz1Ax3D&sUSugqC}T1seYi;dQa^xk zSKRA$j?L?{eyZ=%`)SY0-Z4fZ=o&j19=Eysb+d38o8VCrPjLZqUDC1On%DqgvJ()T zJHscG7Sy9~;gK*8g<=X>0uqCH^RWk@JsKxf$m7eM0M-56`=3Lg9gc47z2^VM75|s~ zZ#4D@v~oCgIw`=gVZ-b<1%janunrd!;HEf)T`{O7LVNd}KK8!8v11&)G5s6jq zng(q83eyR0K3ywmtbnKfH4}q9vq6IfS(}#4?aoejxUmgm^x zjFLo+xm^zV5vg(yxHt)@7akz&>9bEfj*()FLu4ZUd*plfx*ggdzatQs+rBQc+yLAn zY~8BWRst13mU6HJnft>rzED)w>z0XA#ia{J+zU#VUg#D|mW*RO9W z{soUFrO)obUC#9%(c3U!E`mH9Yv_{{a5Asy^Xki%NwOiu9f^k6%3wE33H((1d~FO| zcfP%10QN&(R7da@sDS#!AY?B=-$J0SJEDpfx3Oc!VL1F7W5Wp_2keHO5H~&oBV~Zi1poe3 zfO~Gge>?=_M=nu}Q6i~<@4E9&VlXAzBr%2D;{q}5x3bU;$K42c^TXdUsf(2McL6pn z70Q)Agzkz!QaQw5;&3f+ql*;DXg`1Ztz~T5;<#(Y^^V5cRhh&*anymnOdl@_WR#9UP@$qltX0dF{zqk9Yc5xS zVbB&v{Z7w#pcNm&eF~#1go4$f{r&H3r%Qb7q5Ew6+7&kX>k&3%@^q_IzKVVK&9@l; zC38K(s#L6ObLY-=<9!A(0NgQ%Nm2kWJE9PeM1Q|dooN5N>`HqH2H?s2?tx2y0l%Vz1F#iAQ`%3|_un195h6%2Yub{D3|O*S4g24vZSATnu0-OCh!(^w$wa7}KqKH0 zJMI0&lMJrLV6GH8b0_BZF6LsN!3sMAMj%Z_t)UAGG)DyxQix)~+CInb(?jblL-vU&%JYiRd9XJ$v?a?r0vMA8acm z!d8)CTWX3{uNk&<;R3t+?k-Nv_4*4vEEXT$blhs9AaXKl5u5KZ8{Xbkvd=$42#Bm% z^&&u&2*a)>iI51tkiyg59|T zKk`D?2htk`Qj5B_vQm;8(qI^gwpX^ZULOxYSK1kMLosXukbV&CC|x!P#1c@LWCi(g zwgG$#K8Sy#g~F=d=34CQiQbWp%|SldO%R;qj$3cD4P;&W@rNH7RHQ0;zv>B<6K@29 z=^zaKj_q5mN#nCE6`%Al!LcT;n;Yzdnb3WW6m^E9?@wl4<*QK1CXN|xUlR6r?1Vp= zm4pJ0h=J*anP#=`1u2VUUT@sI+2SzDbEbOIkLR+8fF?^Pj~Z>=*3G7<+}B)oiB+ju z)#5R5jPP{*xvc+)JO)k(L!Bu+8_S|+#hTT&YC94UO1kn1SY|Kxmm|dp2$g-0fM#o` z_)`UIAO;Q`=*Hu~39-99@W%sGJs-u&J25%lI(EE`wW(Rx4!2s%mKRzQx;7={NmufV zppv_HqASNA)^K5~U#Bj4y0NCG&Wqc$0wPi%q$0^jsen+T3*bgX5R)&y8g69@#aO=q zAGo9?$q@G~bN{tcSozPHIN5HvxV3e-wUZ70bP#UBvi2pz7;b^HXV13FQC;M?+NOSI zTg2FXI{Zt!>FR6kn=!vy=dKUo9Z0b+*^plHDSxFQl2KqSv6 z;aA+`>~riSY$y~hQbnE#p>kr4fYUWI?>y1B)Okzs*x5vk`I6|(B^{C;Jy5*46nrjl zG3$Xc@FipW6Gg~hc^BN+v7>$T$tP&E3UVWMNZ##82fX90sQV-gQ0|aJW=7G`M-qBm z%x(XVKP2YAS?``NS?V^d?s3&i!K`mPV*g36QS;T>`6PD;37 zu`iDPcBSjZ17W|#4>vj8CliEdY-m<4TVm5@&b3odJBc7%C5bSaXi;2@l!0v?EOL(y zCs)X7Trt1=N&(OUjr_k5bOy%afDU#K-2vTxT;FsXy~~s>z|&7Z?K-O1(fcbx5&`lG zw(vWZaWv!-=__8BvR{ABFfMHEj6Hqrhvath9~zZYh?E>}Qw(^?Hk z^#JjF=JCgzKJ2S+zTr-s0r|obiMgWH@ewORXdo0;;)|CovN`itx&$AFNL@a?kq}ko zA}AD#Vc)v-7#(f1Td;|E`hmObgLenm(@#E(R33#uGRy+^D=AZUiHQ0dV6a$;$#Cki zXP+YG_Za(a+9az-#KZZ#JEB5GVg=xh0FxyJ$$m?KDagQKBEhLulw2`^WG^>gdo{Vx zOWOzi`|Y=y&<)4e2naduK|h&unaQbk#ijqVLKx{O)=d@(z#b3eFedIEm`wJCi0Jnc zzWy^8EwZ1+jdQE<2#os*7R0v2kACjG_a5utufLtsw25`-)X5pV?MOgipPGDd2CuFu zLI}JV<|9pv3*I`f_37i>4?Eq~fp;Q0Pb6TE7-->@yjD<`NDTsluvzmLx|jtnd!jxT ztA9R6s2s!y_=fEu9ypF~mG~%0u4jt?#?hlkBN^NG@QCmyBaibEa%G~Qc4038qPshH zvag4KWsPc8veCnal5>71`LehBh?-W(X;|NeAyUrujPSe@=2Lj~3@P zx5O=5$Y>}vV+`$tNkAVTgKwZD0=9g)z3^0bySx2O_SP$}+YjG=k5nWIycb}p0;+m1 zk9Q_3FkMwr7JZ&bB9xui@_hU3s}Z(~{+!kNB75tD0TxlYswEIMbeH^)VJI?SkhJX{ zZ)y?Y4=((U%?INFiVepuA(Ge(;jxj{{__9fzWIO7XWR9a{_IH^f-4FgA1@;y4B)VU zzPUE$(AUF#S z6)jrS&G&Fb@*W60_jGrAf57|pcAq!x&j}Ol@^K1AlHk><_>Mjj?s2tb`?3=4T(bx_f)Tmmp5 z0Ucn8+7*s{VE+&7+y-ab*QA#%Sg45Y0AN$IgbZa8AEucqQKIyTDp451HEYt?9k0Wk zO{dd6(d1#40LZpZI&-%wXB?u5C??qa8nIlnCTCgc%2kYO!vj`oa^~1*F+mUw>oozyCgnOJ}kcP^mK%{NLr5yG&z6 z%9OHh&-bui@4RD$PCnTRSFC^(gotCf3QE`M0; z;rnmD%lh)ruM=Pdm=7MDYL7ebie<~mX;De~LKsEP>3j}zGpE5xgGo(98Wtw^Rp@N9 z7U$cYc(b&-;wrb`5Ko?hdP^X%mW+8Xz0}hl?)tEG?sO;TldL?_D9zltsHJ4!8q6%` z^gee^?Q;w}a1e<{5O9#7cOb1BG(?8DX3sn!I~QtJQXY@{a1ZB&Kf7U7<0E)Z-LcCi z5og2=Kj*mP1Kp+H+Ct^PMqu~I9@zcI`(00Y9h^FKs!L7l{myBx!Sjf}gGzq4zxG;t zzu)^-I6BfkdB2~PLr<89D7j#Pf)HoFI2t-6Lg_Ykhg!7yP<8HOB7Nw3-~F!2iIXR~ z3sM6Fzt2eo4)vv~5Nhu(V)6xsW}=p zXlP3D+^J&+dzx&1x8HapQh_v!s8Z45@U}>j1V9h@r5Ay{t0Ct<3B)3=RHM4JIJc?2 z|K2;ko74dHD|_E^t|D~yI2wUWR9fZBm$N2KnjDyjTyxF8Ie#5V{i5?TC#zYj|6Oho z`C{z<`n-$ni$5K?7-c^RlL6xRKgQduZ@dcOjq%ZRh$8Zqc8o4F3eLUg22AlKF&Zh@LuS*53|CaC!^3 zjP-5{?GJneJY0IEZ zh0yJ_AS$59x*T~Vjkys*Ub%8*Ye-5|uW0zRdBsCoiW~6$2OnCmUOn+d7-5ZDwy@QR zISb-?7|yCIgLnHL41U_HCF@>wx(H|(Q+B!gF8gcB)T}pzew}b5Fn#(|Td`uLRf4g1 z@_LPcCt=&iXh=#Y7uAS@g{?r%+ScdIx9s<6vuyst#XKb#@o|%aColFzh4SUCY15`G z^waF4ciy$^@427fk$koqZh z({(qXx+8oyZOD78|7@L-6t8Gu8#s87TO|0ee#SnlOI5bVLO*jJf&I*yoF6)#&jNrw zBx;tNtc##w)kV)=FChD=j_=u|z)WaNEtcdi@TY^Y2`XEmV+ff!OH7 z`Rn~^hmZR>#FtZx+>s(+mSm8pEPVq%{lw`qPa>7CJQI9`IVUE77Ld(LhD`ESh#(%i z>;)#{3;p-ZIfMv)5`2{cN+N_ZtM{QphdNcmbI(2JM$4%K^iGF7eQ^}TxGA%l>){#g-hd;nN#K3_60CW&~bJmg#z_MQ4|1Y;%0m(%mswZ=gO_@H^TD58kCxXNSk^6qT=x%^H zQP3WquU4zJjribwd$V_M;;pZA_5yMZY}BZcJ^b*))}u!c7y|Cs>PIV|9EuDDQ(+pq zKKQUr0LhBiy6*Nn?UymXSb^$QY$vJ-A&;aan2#)SgzS~c4gfKmRnGU$TC5f8})+0vNE6nSC6-mFsAo4}ABbYJ! zZ=1Vpm0i-hjTI|d+GYC-q&3bNtoBv)(YXd3M}T8z{5_MXh2$yly>%(Ou}7x?$KP8* z3_#A`^bSs^i3ylEaUweXe$Y-I@$}RHB7E}~EwK8CrGNPOCo6=7`>%xftzG9-i(9?U zVu;WcgGIcEvPAP*p=FwQ~c(;Z=DNbhYlSq1KoZsVUG7zB#z9$ib{JeWTGJK@hg^E zyGt*zn+d_&=G^mWx>o7Ff$QC?w+qH|#TDc@;FS9oUf%;RLJGjY2=t>ekZO9)Iks%+ zBCCJSS$5ftx7cfMy={f-)*)J9Av_2$#B#;4X&eQCgVV)whG0Vaerf1SyWxw?XC`L) zTo@1xK11ci83ErEG}#87amMLRisU*U(Aj$s?H>|Psswx}CPm@e)ou8QFYHpp?deRN zbUcPoGzP{G(;eqP6ga^_Dw2a2d-kwZt5(@FT^_Pxg^Lk=u(AEG#d)@H)f$V(Uq4KE zNplefLkWfUUVL*q2_rw{&zLZ2f`h8NI^AiuBMwOy77DWd_xE$}^&I0XFkV0Z`isLe z%CACmW&Iy2xg3EYjF-zAj?c&brCZ~DUCXeio_Z?KODCdZ)_po~ptZZ?5}P?|HhSxD z8}`XSt4+e1MD&9N0m@WX;o(5Fh=&GwUjyw)2!f>qffpX=fd{xm?@A}WK(V65>@*17 z=R>}?^@~?nesqr_wAv0^p)LjfNkgoN=)wAZIKWB}{jW})lW7C(K)kR1@2%`+hZoz$5AS zepf&3RBPUp6vh~D`E(xcMS5MR9M2;lBJYLM>RWl6^CBnBCOrZtL;V3)T=KzH0Rvq6uz*E6R7ZEw8N%bt1p4XcY4_sCJ-T1=J7mVq8NnQ==|ya0(*#Q?Y!K70C* z;fZDtx!!g2t+sB-3L*odgLPf;r7iX(L%#Qg{vJOgAnM7+y!_|yzY)J@+VxjoWf^hX zIZ_H=CV^uRbQ|+UbBOsZVwDb4To|VFhw-EB+76xVz4!ZIoAQL6TBoi9^(69lh_4WM zXbSg!_h>1~EtJ_b1{AugsQk@DfA~Ng`y0=1I^tRm%^qmo0?rYn9|A~2|FB~d4 zk3cU@|EsVaQ2^GRo$s`p+uv$uop~mqGnWIHVRr9rx7oyTsi8*WtNYL8UZwm z@C$7?C=ae%ggSf4>0I`E4&rwjx^!nCNBG_Io1N#LoI(aZ0df>s^RfW7Ls*A41*G3B zN*1$8=r&`BE3O1O$y;~0NMcGQy2lt~?@KWAqGQx9v5F^v;oZd@I@mQAUuI1jp3QlB zAf!r#ufFlRjsN`*8!_xl#Q2CUdB!U_Nd?@)?uKyd`pDz~iO5GB(rXmU0f$#BUmt1NEu(P=5p1WO*N)wz@)IzU4 zq5Xe-1T?qUm8FLkEfRHw2v6^T8W&;0;LYaa=Y%Dte#~*vdZs^#- zzWRQc-F)k@uJ+%r@a3EKff1<UMeLEsZ7n$lGLbC&`pZwYeZvMqh~EQG z5yA0V_zVnuckQ%u@eGihD@-DLU^pPv3xWfUy6}MDAzefe*ohKc!RUTT9*r|65vqU1jzjvYGM%Wu4;*ntGJ*=70RP}7Knmj!mR{5XQW z4SJ8lWGcmQGFj{zoOPD-O8E7+v0#~SjNX#mO4|`-Jrnd?Zd>QP`B~`<88XD`5_l)3 zL~-Xjr?9^YRB})SM5NpS0(9~8Y1ml2Lj<&4JGNNQr=^AgQK9QBQlyYQ@x&8$-3>Rv z70?O(%SdzIWp{_~Mwh?n-+4}-+UxDNtikyg*wnvgS%E55tRMznsRRv5#+5O>U_K)j zAgj4Zx1vkH>N~1bY3qFNeKvm5M6wr>Z^2)rq6kR=ywNy*_F4d>utJtfY0TKM%(E0r z+!>FJkHT9s`<0zah3O^TelmLLNLJYe%9XZG_uXr6_UY$>?Of8f9X3H^0cHL+Y}m+w z;Pjb)xkpo&J6B@YQn^}nd#UFOEI6W3FJ5M6qH=oX>1S;_#;}UcmtS5hNTkj@^K@E8 zAWaO7vlKD(LB$!$0v}?UC7F;Ka5LinZ+;kOUGBLTa6)~Dx=`~rz&Hy`{3UB`-r1wP zr;TD@Vv7{EDU&DJm~p>3wB_e@#vSF>9CxqF6W=(mjw(PQ$L}dVOWWO$p+PG`G71^q zWDwFeT7U--N6F|7SaaLa>Xg?k|2`ceuiW*@QWgQB?AY;E`+LD6+qhL?76&Yz}ana1_-TF4NwxVe@u~QiT`viNT*DJQ1 zh-=L+zSyorw5yQ9DP&YEP@$qll59m=!LsG8Se0s4j>v{uu3dlA4X*Z=Uwzdf&z*!| z-cFcjrIZep<7Wii{03g4F+`Q5=jSn_t#pafmLG|c!b&@%Il3$RkyNfHGdH4OfWz=p zKjWOnHh9&9H8K;UU|Miz7b1dqaJL}f1b`mYE#;%4c>v_fh+BtFI=flZxSfBvFPo#Somo#*V(9wf061l6um8an16kV){{WRuR ze2dLmwP@*F5FMgoOq>y(rz7<}bzpxHzlRB#vZbtEVI8`3wyQ2{Wj8>ek$d8QEg_)U zM0~Op7hnszP_1G-7tOuCL?6yWc47u#G`c?eFuKtcyW{SA?8ouH+imwfXeDdavC9cQ z^z)xnZ1uKXHk1&+13vi3y5NF!9$p2_TegDvh_+W=#VY|sT)K2=t5vI(Z9rrjD#zCd zXv(Na!X*0JvE%I)Ma=#*=DyrW1y9oVCnEujC6nF?BJ@>5$G-#HluZQXI;rj{FsCt0 zHKpms(w;dj16`HX>sC2K*#{rI-_9m$=o$4+v){-5V&8xJlRb1#M=M&Uv?Y@MHy;Eq zhRwAF*v*$epY1?ZwS{Y52}qv;_yCbPu;Q3~NwIiN;{PGTzOhV6K5qa3KmbWZK~%QQ zn^@th)h$I?I)MW*2|m%kdYHEgRu&eHIwcc{=69n;$p(_X2zc$0yw%eGW^26p{oic; zVQBTWHx)k?^cx+Ogb_6iM->Jo@=G< zo;!d>2)TF#AWQ*!L{}(lm$bVSZ-8`yCXKVqbsH_rNgxDKzbz3lZ! z5{yc|QYCF0whfg}I>WyE`FlIR6}n3yH+p^s7Sc+hGJgE{z0{KJv^U(|cku7^8UC6% zgH+JNY&81Uzh=yG{?_WTZV88RNMc;2XpoAfLdD8&n2*8j|Rrl0K6!Y>O`RLANIxPc73P&?3SBv zu#YibRZ(i|U@2P|vq~}j>zrK2TC{9o&prDbQ3b1zL36%UtXSU8s8h#wVobXb@1pR8 z6t~4Vm6$K?L^|*uQLLENJNE)BU#YzPM6}P;ty?S%h9i<|0a$iOLBc>XTrzL-6AAP8 zNt5iR4!7HnUw>_!e-D1lANl>6>4Fv77FF$iW{= zmw#yXse(-pocB{z=<;4hKw}sx`y2sHv5a;6>Cg7M_;Arng_l*7z39RPEiF321?tFT zMd_#o*IhYK!s^|h%e{MzAK;xdz}15eot16*(xt4yskI&8O#f#t2|x;42GQ^$+=_y} z?XQhqy{c2I2ya8;5rH%y33tbxh$$bq{{hPcp`^==NgTTB&5e4&wcYnetCMKPG;Z4_ zD+Z(SLifiopt_VMC`2#@daTMm`|L9p6lL}5)j?10<1nZ{GEtBqLWW~UG8>jQwSSf`vxmBNvnO8ciGk|N_TeX=GO-*0 zu);=SC@&ZPCbgErOSgfERc?#Z&ZuWKYu9k0t_Sq%XRB7Mu^+zqo)teiFqmsfnkB)f&@i)d!J?l)QXjuMJ?;#QY zp!Xc9!!)%K*Tpfvk9XtmUsk-TZ{qthN9xTdM!mjqJTdy3>t1?ZU_fD9cvR#H(Gc4JD$ANpl{>*Kd^UCfk=I zM%ty9Uty=Y$fj zc)|LA_^~ZqyWYO|?mIiTbz6JyNwN^&7^CHl~4d#*8O$k#87Rw_q6`( z2L8aQ!*w7c?-B99-q-F38tAl!NC8@&*TM>eG!`yg%t{y5g(hXh5&aAOwNFpzdnQY> zvaH_yeEX@2!oZL zh%h!Y(Y_hd9 z{tY)IJ{XFWD=wu$qsH(E@7nWN{g*3U!5Y-5Z3O|te!X5J5AbHQorwE+el-K zs!9t0Ed*c&@>B^Be{d9xc68yg_UpK@wrs;zyezc9${a>}6Mc9u2fUT1I+OPsa|EeV z-tT;FS_lKMSkH+Yowr~CLF;xpjz2vSeVw1!@0J+k<_!n=jG$aw_QE->XJtiP2ut?2 zUwPfNZuzPer~&e0SmQ%P*&oaCw|j@C3LBjZgV+gq#1XJ((W2#c_2n4n5!y5w;bwp# zQAK-eTaGW;%SoqBfbkHlGsX>DwuT`Hvktek4?IwbU_K|q0Ni}@%`{O)ka%Q>_~$e( zfv0jl&KzqB{rcmt1+BJSQb zYu31Z=+E&p0!l(Pf6+pSdR5i&Sl7SF0rmw{)hq4PRun-_&Mh^alhBC zM>`2T24VrYv%Wu0P!|KCM{4%fS6^9!Q)*kKYSk4JN91_`T&%05RxV6M$q0O&y+B}f&XK*Yb9b7oltdUl2G z%)l~O#SuY2z`7I1@Q+jhiuHZ=slMoAk39V}2n2s*!B}n}iGC#!gIu-*Lp~qu)crSH zbDgEZ2)TD14x%4CUQV4NIVeTP_%RRs=mYy}+I0K*J6{|Sc?JBy%52W;+1Bs9zD~rd z+mmIC=r7(^%)a-odwY3#D1poKxJ$|P>w^#a+a(vZwwGRf!MSancmDbI!iz83+kN`j z)6YI@N)D4RUp`C0NYTp|;nfw||My2gIX~pyDQ16He7p-o-L-31w*v3mw=ahE(N-3N zI$8Rw6e^_bexhGkuQQkSR#vZB=?q4rU?#3Xy;PnAJy*8B#WFT+b~Y~VITwF~qaa)o ziwA(1+>HbbO5oD6rAveI5@dTDtCYgUOW7PGRvS0%Agu7Sn9!4ER#COj{(zUabz5Lmz>V3gFtgx@V>MFbU-g~VvvDWLIetND6vh@4Pw_decHCwi1 ziQRJBt=5f9geRYLk`w(#b6rIUUTCRe#fl_einWm=N7^lZ+W~h&=+A$C1mxkNa@*~< zS^4tioefB{X3cCG>YpEBIt#-H%L8P>gbB_brAGA{?tYz9(TY7-3gG3ms6tGMVn_g< zd-4g3BcRlHa#a}dBogD}2r|Un@-2d4s+shHAwL{R^q&tYm26R91#AtBfYNYlwJ#}v z7SKHH+=HD|062e@5W`{?>JvaHW&2ic#}h#@Hi!#gs0j01fx$@u*dqyZJayLJ7LU9| zODo{*O?fqh%HbP<5Cf3AvFyuZHv*&fDQ-C3?zzjVU}%$xEkHQH>52dm*gfhcpv?BQ zLz&1jKpJ6DVRk=ZMgJrM*qGlY*i|I7N!q#GVp+lDTtsw5-hzq{3~7J!70hqzmMyUz zgeASZ)1AmYcVbb@H7BkQy8loPgP9MtLx9gaQWCI?-niaAV)fPh;_mm9( z6vSmS{@z-B{ruxkmPkx@NddmWEi?g@OMdJv+`B=(9`g70*$oA=|K3m2LYI%y2uKz5 z+i$TZ&jbp{1Ee}d&B??7%;%C<}V>Rm=}v;U#ow0p=QmRwszHOd+oJ8 z*7MM}$|=72;_(lTH8 z+>99JAF=*NkDF+>U3IDDCyHeuAmq4h(-W8ufN$ELl<$y7A`PYa^lD9S5R@> zc+l@-aG03@|4d*YBX)VcGwV6u_BY>r+rRoh(9h3(0H{_Oic4+;|M>;OoD!%$nvk+L zof!EFQyQSzhZ~`&Vm4(KRML{oSYOv`aRJ7S=h`C=b>ky|$RNyMWc%gkpY2oJuq4Kh z(F*4vi-^03e=>CzB=u-2*3y&y{L}jOd*8Oh@MzzZSnL(bSFm%=ZfxDVcehtqVJTsh z%7_sJT%vfn+(qEEi6FRuQSNH!PhKAZ5&1VsMkVG>>3HYPolCUKQEuh0AYfl&|8d%B zr#V%?tXZ?%zD$`idvwcV{Jaa^3RZR_<&Y>80<^BV@(N3Z(Ui@O67p!Che_P!bcx=R zzP;2DiuPH%c5Ua0w1ogUSRgysR0a4_*xYb2^)Lkaflq}SE?K6CJ&FV?8EJtaUi^jT zWS%6T;z)qM$l}GU*Bh_eLhNd!ss#58$v&1@M<(w}C?03)`vv5A2mZZQwue$YKej#U@YjosN8+<2_65sS zAP)Jtwq(^x+c1;NW?Bizk62O*k7#@C6Vdg~32lf0&<8Ng{%Z=il!{6Py?GqLN(#;Qva#i~hf20#qg<*1hGHTS?2h%nA~VJPyC?7*rq0 z7$e@%xg(4~Gnb?N!w)~S?{EiGsY4)_Zr!@My;Kq2N>KAgTlV>u{kN+m^yiq4fQ$ME zOcXC(+*;#pGSbh~1y5bs07*<=6hgHF_gAf`$BrIj7a)BK6eMDvf^%l|GR7Zuctsla?x^-6?LzSzc0ooi{rEg6~hxEczy;RfmO{Ryc6azB=D z^61TpsTub3#3{B7PP`ad;xdSd>!Jes>2L0$cf-3e8KueX4&DR6t*O7(4Hf z6YbER_bYfw27QW;+hwI|)U=+@KW{G*4p-Jz*=O!qxgs4bdC^bf*l4nLh^h=*a#9T#Ued+VR|NeWY&RH;j0d^(# zS!Fy;RxDpZ0Gep?mQNTyZHeD1RI~hr14D+cdxjvSz+GOiCZMDh-BvKmg6c~Ucq*wWg zj=2V=V#dsQ_WEltz&VIHmvlk%T+u?Qn^!pEpY0v)y~pYg;}BJ{gw2>Z$rh|w?&28G z@IPqloa|$9teSW{z4wG?01g2m{{`;&H!Uo@uEKpz`*)tTZho#M#qF^CLG2+FVrpL~RvMxc5feTzDl{pufO3QF>z{jh=+BWE zfo#)2Q&%)MP?+o8x;|uo&p|>4v%6&JBDbYNSbey{Ki47rBL10vQPU%c*fozliI1CZ zdKYzPX984jr%s)0(Lb|o{2${;cU|A9wlZ<04GVB0Jget}+smo0;f1AWpbD zwLi!bJaz~9sPA^QiFT+SkPe>zBvUGFpA7xlR&9v$bwA8TXBmfFy(jcgP9qS&MLAsz zo!jpSJS(8r;(EyN;qn2(cQqe#m0^|GDi0JPB&94BkHR7c(f7zz=6 z{Z{e0baIV%r6s44R{2b;QLVa-_+l7IiT-D^ApZ4gSG6JUy=9AM&9=)CRiJn5~KictP{?T)67! zSX5$wLL^3i!aEt%w`=`c`+USV%*XplDpbx=fc043q1C_Y3Dll*GrgA{y*)U?X#tQl zrXkT72h*LY1%+^l*|+X*=+9vv0nLL@$^8iYz@v`pj2So97X0-$k*kWhY()(gg<;21}@H&vY)SP+$SW_bY^(XMp+Ih3>&!2v>tI-d~Vh@n8YOTd0 z&drQVu#^?6?bIsO?cNTZZRo&3HvZf1?WHFkwNkh=^&@t`>8I5tu+Y!03CXx(xusZM zm?z$#9PfLNIb|=xuT2@|w2we?CrTPY`dLMO97mSR&jx*pk^M$nw`P^g)~Aep9d5sc z*!>kT7WK`iTRYrpg=Ci!T)g)Lp9?xxHpwkpwplFRBZj^{4GBXufp0V?vlQPecAxUQ zpdwzhQrIX!^6g(#P=aF_u4Vwk;T6i;2LnEG3zO@wz0TrM_vOPd&_(dfD+GUcj{-+p zaD?GfJa@r7TS(|-F=dqLY=7$@7(3}W__wZy%E6C7Xbca2%z~d#?BCyXVl$yT|HL<# zT%8b8X0j+x9w`B_B*c!;g?9E?4V^c@&=JGQ7>L~hh)hV((Z>M732Hy93hA^BW1>k@ zCcD*6i3*i0Io_8}^jLLM`b(EA1>?g$L{a+zqWsU_GY_gcTK!9GnuKNb9e3Pe!*C^B zg^{G9391bFVz46)jY0h5$BeO?+FfC#VhWJN9q$V4AEJ1kAkY{B4EWVhVj9=sp9PYK0AbtH82L5+Z>yGLv@ zVQy8X@{KM+)zi2^W5ht2wsOT9yQ5=gyY;49?S>m~wx(w{vNGk$lVGbPb|4k(F%kfY zQD}lUh+9^>T6E~6vYvV|*apCZMO{0ewpa-a1$93} zU+Mrc3JxUs&GYg{4p&G~Vw=xK2YweTZXuI=tU|)PXk`I(%A-f6&|aFF$;xTR+O^gQ zF@60ywd`JEGK~Lo5-kW~V1n9{{j661vikq*^UvsKn7zp={j_@ZkeH}sT3_`0a+Y}J z;cnPa?64G8ZBg{u5q%nv3BnD-ayg7uqf0G_S#=DEJe_YZtAb?Wu163-t~ipRK_3jT z+OPDso_+e-pn-$QC$P|d8}~aynU1eH>XlGADkC7Gqx8;Rkyw1tM+2>M$2;6Ce(3HF zR+g2hn8HexDp?%gFM&-ifpO%}`1|kKE(LUczUj32ORyQ}MuNa%*6xbSowUsP>Z@`n zTPD(-U{4P(5RlyY6wGJ&%EeCd7KvRzh9XyH;{hDts;Pd09U%#Tj!}OlLi7_jp0{wm z%L*6+vl&f5tiDL8wkD<6GfzE*d~%!19T0|EK<q?>8+aF>WLD?Y#AO6^_!e) zGG*#SYkE#IJF`}Gn>KEOWuWp1_go!4TL*V%&>#Qz4A>rks9^_Dvk*WC4}~bw$$s(8 zSJu9ZFQ!R@h7D{azsr;=$7(V=_7AEzba+@sK*V1J*%|EdWs>4|*$4dx*uxm{)vi?0 z-s|&*HAA=V)M2R*phSqWiegGgPr&z$C+U-jR$&6`+F~cCKFlsAUA5v! zNTMd5(3^kWyz|~KMxa}ldu;w+lkF!WNTzSt#w(Esr6l@TR}U^c;;(t7Ifo~SYMh>?^cm_llEo600tB1``gw35X)51_;WhBP?a%p&tQJvoApRcZu zNBa+LkgCnuOfi0ugjD`@>=?W9mfK0M&Kko^D%Q4YmN$Mn4lZ7og3pDH4}1jnHm(O= zL+DOog=c&zfJ$VgI0Azq1?G_JnWE+$^AaGkf_UH_B$l#v9jn~ata6#6HbUYyR`=2! zdj9WTo1JP}5&^eb%CzAaIyP)jALLVza0h^>W{-!cyoZkFo_A-Wdsh&m_?^4#Ev}hr>fR>%cqBJV7ca3Fd%WOM{HhB=Omi^sE66A8{aklMu4GS? z&fYOSezfD50FHzA4&@{H0kLZ6!Wmb27=*I|%S=eLWWv5)-?5Xu^Wt+bTxK(;Pq*u@ zyD>!kHRwmA_`j8Zo(71&RCN6R0?!dy@Sk1xWScPhXKQv&Q;WlnBYx2mOTceFW%E`` zT)z>IlU4Z9FSEF%%Pl-H*$M+k5m5O7@AkFU7hH(pXe!_FI@`2)gR`d*@z1FQ-p{FbFFVpn+>*x{fQHH$* zJZ@*w;?^_KcCK6RR@xbG`Hs^*qA%Y^3h-;J4u|7|-pIV53TQ+Y_v_sOZVr1pS z{Ei7gpX&BrO*!m!U8_bFYzpMQ7>N&e@`8od8GD1CPd;v?5hG9f;}3iA{`-Bm=~j0X z`g1r&Aj?<=F#)Q3+JrysfqU+=Gpkp#G5Gx#Le&+we5FOR!p?`gU4Eo@(Gd9O(9ZLyH$JMZJ(1 zu;AZ~kZC!LWuX23DqRY1=1@9>y#O#=nVbTWHYjqT5u@PYu3fEYzA(G^@=Gm&)YZ;L z#`XKa+O)6s9*Jw2h{}@bKp0H?&duBGr_p2GngZzB#QWwQiFbzT+&u!j=iBacp`(Ku z0fsOW@7#>=@3rQfwPd+XoHE^FD^|87iPHDF?mVcM9Q@5r?V!)g5>{#g|BA;29m#-@ zp&M+6@493Z!$uOm7AxV%V0D6!2AftkVMM_j_3d|d#wm5}oaX0SJV9~NGYNP^fT07# zbqC-61ARj6MBiBepP|&v+pS6SmUaq3TiTH)Kpl{Ee{e}*CGMS*7cwJMY+tk;4#slC8}>;Qs)=mvF|t%v}lnIj|AXh-nnv z7YL$%NbGDqL2}MLx4D%mQoybJBl$2XJGMI_k7Wx?GG8H$r{#C=-|Kh&sC)$FL%PQn zt8c$~qvcCYwC@HF#QUS7Q;+@n)6eMS^=81%zqud&KU%#@6;OiUJ(<)m8=EjOv8bM0 zxM&%mBEfP}EJ>GgC}Bjpih_A;g|tg7=2p~GiSriP>Lu&!zB@W7X$Fx#36bp>dFoLA zy)B3Oj>##;I5IMy#Y7jdh_aRJyV2t?rjB>bq{TlTlQx}TFZJP?6RgvRzq=01`-#{K z7$;7h3c|+_41%g4L3yj-M=bZHoja_?$*0&!Rm<8>SkGr}-)<@LtIt*tTs!^exN+mG z+1ckf>*GvTvOY@YCvMrEIeI_UUf-r9Ownr2mhIO2+2_%drrDTZe{qJ7y2G333f>}P zNEPYayL9Q|a<{+s`s*&=yL_qTF7-2+-gH+JT>o$eXE7$EETql`V;9&QvG<*J)W&}c zXLc9O0U=)ssNcxTWMPPW4e|1YEm~T=8nr;wnRegZcj3dG1{070tq}oG%R}W*M!+{a zc8{Yzqk>~ybJdm3g>D>kKb-F!w_!bca)`0!lWzCEqqong5nPL4)t|9>y_Km{!Cvq6 zq6@|Q_@j>yHhPEW#+K8Qj?gQjprim|7!|QHk@Vtjn&_Q570opjZu0dg+^X*hw#7WH9ObR&{HbwUj(ZbpUOae&jHCClMZKC z62X94V;EH!cg%b5yvwyhau~0O_y@OEDP6C+idDXr<|-lrtk%C8I>H*^X4L=}uS|l$ zxZWjApP9Ea}+LMMvE~;d4n>BZ~O`AP~ zCaRIPifz_0Zrus-dfzNQA-Z}5JLzWvAS|Cpf-FRCei}W-#RQOLuk`MDr6{0Js^<^9 zZHt{$tA-BpXc#)rGu?Yc2j%SRQ5qkM-4``00VzX(`rg@mnJtWd>r_T zWLAWsau`Q|@0N^}{hP17Vh!rmv5Q(=XmQJykrErjSd#F#cmRBx1OC1O5&$L>rdYWm z3S!0n7(uoQP{EgoTlH%gbe^5y z(#>domnc!fsW_(0T}T@02zvt;KuN4*hY%f&AN_9L_b?9R;j1b|xDlz_*WZ5!Tm~2* zbdsTRG)BO~g-7FE$L~7?WIkP8-xTD>GL0Mg?I<$m;7-OW8$}n$1#Vo(B~UcU~`tNwiTP!JLHmz_*t901LCo2{%z`XyNF!pJb?Nj5+?^A zV)25S1iExI4>aC>#>?%6NZ2w{lUV(1wCk_D+)6}6*wYvV$}LObeN`j@NJZ}|1o}LQ zk=nFrK|>{i~oB@L1|NoxOdaF*IO*^v^{#iWYdtG1sBb^OzxNJ zN#9@b0#aC|E8c+OQN+l)Uy>-U>AIUE!4+^xiGISUe@7A?1I+KUo1Eily!;1lxV62- zU{{cgJ%Hi_?9=jJUCE(4!LK_k#{oFaUYk!6ryyh`PO(}4&V`W)7(I^3es}2ikr{yy zMmZegDkR}6YXQ4i(#cJq^RJEh`B#g;x}GJsGx7ZMDU z$~SopQSUU|>=e96Oh9m1ykxP>BXi&X{onstA`%0)_Cma>kV(J){=1!wUcOG9QvybT z!OtG9W4|!h!sJp3bJgv>`#{`g1Nst+UXr6wIph(*Zl77O(WGtu#)!&njgV%+ z3Ah9~QGS(-z}TsabP&Als};;EiLE1H)Y9UUtT=J^o1N3d3PXegTjGlx z=MoD!H$;EG_NXS$oCvpqB}&=q)vIjM)G3Z10jn$nl7GoFO+3yU58`sv!jtbdn?%tcX7w`lVH^ zTG7hZss%B`Bv7klSwCwHt>a@|JVdSbun8SYv>r#Wmj7Ma)+I)1-@d(V-?h`^0pOME z@Yya?wk&mmtR2N@&FeHz9xi!(KFZP%FgnA>y}gwc@nr zqxbp{(>>F!z2*vwOWbwXUwNWcDB`a#r`eH`o@^5*{$bUsRI+jvD_9D?^O9%<7+U|} zI2Bl6UU5?T_I(v#T=Oo9&4@?Qg@(#e7=iuF?4!_vS0A>(fJP)$Em{Mf`&infGq?-iJ>>*L~XQXTSv1wG|t7+5EY4tYFb1Ru}`ug|p|{ z&V+Qk_wLS!!gpDcg5kKHsdvHXEU4mxIowOz4yKC0z211jgcVXoMx+463Kg(x+FeS1 zfWK|l%o#4o4>a8cO_@DwmOY86U*Afe0g?}BOnP?j;f@=eahhfB+U5)B6ZF{v?>k%v zvMXR-pd`YVYb$AmFU0?xfKtQ1#z4xqay(qGIuYwhRqO^z3hu1ynCq!T_Iv8#M;UXZ zMb7G;c`Thg%&ZuJ;BCL-<(E3S`y@T$;e?%A?bLId*j1Naf^qG3d;Qf{oT^QUdb}cO zlNbPn^-V!7u@QfL6(|1pZu0it0)jb_$#Eg1a$yk7i!Qpz*5meiY1=l2>fc^`@>$f4 zQI?F#Dx5j(;L`(gudY0^r(yI*vHvp?;_YYbrP3J>pUGmzx02=sFbwzT-ot=x@=WjZ zQbY3W6v<12w6C_fi5Wy7(o<76kURW)J+qel++Y1X+N^8^OLrE&yKmfMm9ejv?CY9V z;Rmy+E;YlC@M6?1ETFHv^ioFvfBWNi3uA>5UaX9L^2uk;RjTQk4T08lw_4g)Q*wRH z599*$1KwO~eTc+8)j@+1Y7`*rHLFFP9 zMKTOlehi`>ybpIku8kN*fJx~xD4rPE{RsUzpb^j*%DP^JC7hMM4D-UF!%gd-Mf&C~ z&ahSU+DWt|)#Cf_b<5;h_RT$`=hy^;e6{p6Y(}=Mu`4dVz>4zeei`*G?}_%=7`PR# z=9?UbnFuf*G6al^OLU$e&g(;;+hJw>VPkHjB9TjmbB!oc$gE^BdjzrnOjiEmMtx^H zHg2{^y3pvfGwlD{I}ZRUimZ>noz01iWLTCYMkI(JK`~%L6jTt*>GODbro_ zKkodEW3qd~YiHI;E(!UX`k ze!OaabvkG@ikRZP&|6~KXK%bkXkhfwIT%X4@zz)(pqbULT?gx&?s$&0zh|6rhWjkNtC#|5+}|4ghSlOMS3I_h*aHTm zCb}Cd>kkOqBl1oqgXQ+g#~ZoqMZ@zYNE;YmAn?gMh5z1vTmEzZw6HHK||6 z8rG?=2v=6foDRD8af5E!(Xm&r^UH?RHW4+mN007y;&HtY)fd`}&%fX*-_iIrz-BWn6<8L{*D0v<}C^DdQiKTwtmA_`xTXp zBoK{rkbk zZOD)_?1b~qu~W_%;HLWRf5%;wEQRV*i4yKYSmK9j`XX52eI%O-1>7nEFTPF;j9hGX z#<-Sg{dz^8!@qmiqvr~NfaYwpR6GQ>Q01Mf_O}(wF$Vm|5^C3UjDW}LR{Sf= zP@`K|STG}gB7&Juob|Mt zwa~2}Z{xrG$}YL^BD;h*{OKe#ayv2%?zqhsE|`Zk@=_bn|8(TWh+RQWeh_ca=Al&U zg~-B>Qa_jH>*h6Ut!_r9ojZ7lBU+b)s&u`_MNy{bc#yZ`f!@9)5&VFDWR{s#UARPP%)7ck+?1vJF_i zawVTJBUHd46-T&(s9C!4WmbD|2 zymM^S@D(W~?nD35KL<&Xhn;@WIcKh(T^P!JD9 zP!^=KRzM8b0OP;<4QkpG&y2GFV!bSdMMjGZD+0m9$&&#B=?V*3V(W-3YFAj>60wX9 zpyKG(r7JcLvDT4rt#QsElU}RuFla>}&$ma9vCJlo?cnz9Eqf!@|0M1SuctEm>KF_N zh+B;4rVGg5-o90)bvbZ6}Be-sbDCd!mS$Q5@a4rq5 zYyc{|M3d6f z>>p&M+_1UG-XHUlbvybPyY8xM?A!4ZERBveB~qtBL?wCH#vrQ4p+hf=kRqH>plG8Q zyymjuQ1rio5Flv&rxDW3KU6a`OQNNcAi&&yJ`Uw`9v{Yk_pK2^uauEbCB1l0s}-S? zwJ_+Y2m%v>Me=2#`1!rM_ps-me$raC%nTwXh~+*bf_D810>RI&CkR$qX4|Byc4hVj$lD{rGAWVxdt%fxs5~14p_S>~K#(rS zSk0O>ZIx^QPz4mPuVSL@vqDl1pL+7C_RfpX+A+P3v5SWev4@^|){er+@OxBRbqEFQ zCls+u@a3@;Ve{X;w79+s?P!@QOJF0BirvFhY+EKwn(Cw&&I&gWn7^Y6JyvE%zeTT= z9|BPZp!_i0RSh4>%}hvq_WT8Ar0$!vbhZ!IKUAP z`HIU6pk$z!s&3gn{63^`f}J7(%IHq29tE{B>FO(^u)}py9i(arjGJs}zQqH<83H=7 zk|t>|_e5s9HkMAh?R?@BXf8U0%$!vSXnotbX^Zvld!qI3KfsRaex$wr`n%R;|JFzY z-m%u1nU=SH1Clv~2WCBb?tbc%q>E0%s4vx7N|JCteT+@7Y18M-v1|`N1Z*0eMGO)x zRSkhC15mjT|CtTumq-QewKw0k<+JBnAU?^8usqKzAo&RSx~siNmyfPd`e#2WQ8Up= z)=y2gwHVJ`@%LM7|IS@)9!5$v_HS!B5Pum{;ZzM0rR7pNIwXUs9DNk6EoK5d2Ebe7 zmDN%2J;JFvC}OzO4y9wxlP)y9wmtRoDC^XNxaoWqSr6*LLyg7ONrFA%t* zblbeup&o^LRr;3b_X>c3;2bTL3xP?($7|6;fArbsmPEMMT#&S)bya)1S5E=~6Ci8% zLX71O=-So(e8pAHfbQ6%j&`m^hjr^_zx*`OYGgFG0O?L$DpH6PTPhHY7I+YVVj^7e z&Y`bWc`8O0ARQsmBzFIku)$bHM8>=C`;XVupuUuL$^}c-|1Ht~3q30npR)^8A3(rW zR)h#cMa+o~U8-Fp-QIi8#g!@!DeK+0qqCQ2Cj2+2m)3Yu#0-7~pXo#Z!h{PD+I z462Soav(TkD(8|_9pmF6be*vRhj=Ll!@KViAyuNJT@(=ykHCAMb@rqJVh&V1hCm|m z-+S@VXAxS#Va84cD_Yjr%kc{KH$0jsfpVfxnRKp_e9IgmM)k|anm6f z)lq^(p0viH_jg13qMf>kh!}xg6+J6&flZq>+2X~EZRX6GSeVbSA13@@6NrL1fBt-T zZN-Wee<*c;Qt&G9jKa{aRc;QX0Pz^)iV>*rvV(aeX-lju-?5`9E{K`*c1b20H*VsB zQ;Gj}!L?{t49S6F5@PMRla4pxj%&%s(M4-==`xsXd5Tb%ycnuynih9sPd<3+IH}|U zku4l>-4MgQ=XVqqPbG()F>>KVf%$!s69y?Ae!Jw!hqX zgKZ@ht)u_Na`WnfSBPK=k(SInRX}i2RdrMf&2SkF5ED9WbK1+7Y9E z15UTtm8&3{LPQ~}dFNM6Mc(d87_Jg?zgl7a+QzUb#zG8j*a~t_NKQrdn+|bk?B1G@ zk>R8Pvu4e*Uw-+;rjpD^#7ruT@4x@v>9#lHuBrQ*BUToXKa`ZWvKyE?Z?4;AW@0q< z6T7e4wQD=;^SW4&r=+B~I`o@}k+LKneDJ~Ue!ckj;(1V$U{Fn(HMQx#&Sab=h2tc9 z7T{CiM3i+!>30s2E0AWo0vaezHA5*`s z-E!SuZ0_87c1oY#cFWy&Spfls;)?QN08nm`UtpgoiS!B8VgPAVQq4N{;b))Omw4Pr zA{y`oKHxNGpXkT$w2@H;pb`f*Ncc&6?ZCZ@yyv&pg`(pMR-ci3`$wcix2^K%8w^w#7*g zlCFZEwE$rgO^_qay;}3eSe)jyui~ z^e$bxIO5)(SO&?sHcGslhFDo4VkKsdL+84h-1FLzt|#-L4C6Lz*x(on8OLdtDqnOj z_kc4RbknyiJ*oa@G#?5e^0JVZbgMZEeFNN= zDdT3lb}j)`X`!FgFafxc)oa($ihz?$#3Ux$^;iDMo_O^wYt^uhJ@drl7GT^8iB73d zVvb?)RCuoK5jsd}V}6b))v>cSAsXt$$v=gNziapl6%G1meR~IiC?hBW zL7L)!tzEy-X3w2(jgRbsI7~Zdp(%>D>8vUm*}Cs}RM zHM>AY{JJ|`zJ3>BS5O@7@^zL(A*gOJ>)*eBao_ZQ?fS)Fcs2vYKkkDcWXCDvPVG2b zwQXaceg3%>-E=mmmRW=*M3kVw8Fjsgs=*?2~ z>&!KNPyW!Kg2Fr((J+g-JmQ5H96S;dV)OEHgIQDeq?+hGl>>pQ#m<$}hls6J%M$$4 zn^Pk-QaC;r`ObOYj3;v&VN}E5`(lx4T2&}Ct9V^9=5CO_Jar=ta)D|NLR>R z`1SE8pRyZny4h+Y>Q)Ni4jm4)8*jSF5&yWDIJ#MgUwE3;tXtdOeD`ha8t5wwiv$@( ztPCAhS_E>ASiv0zKsxJXh<()ziT#}!7vT;s+U0xKM2vL5 zzKi&K#qIEUpDW&(arfh;;xPx_y^(fSZ+CWtw>3#{;(}u8OXV>eJBY1_=j9Ecpfn*m z9R5hzKQnJc!11RE4kUI4AAR*cokOCS&(_r4`S*pthv9qPR%kg13Nm(+ZVMvRD={2XsHPCe-`0+cBHB|^j(H=ZilZqMpf?MVOh=l)GvW22qMep9^IyM zu9!m#-jc;<@15SYd_v%QMFc<$g-5PkC|>W!&{=)(j2>kitD|^b=*24DOZe#e!#Nux zIQ2+ubl5a-w|ckxRTm|mCiFjvJP*KN4Ra$NRaXvbfN~eTNUxv)ei{=X#)l8WU#KXO zc**?y>n~Qo^)%c$9kZr;LwyR4Mo@y|*PMg+D+*;CZ9e(vzIN`Q^DIC-h&VB1^vV%S z*HNSk+#c(_+ttYz=@<6q2nTAp0kNYBV5X6=1Y(mI-+24*)6d;lX}sXazS7uuJ}=fB*Ae?CQ%dv-z`TS}TmTY;(wfu5#P4``U$A z9Afg&Qt%P&GDKMQGl2k|STdL7B!$_VZ1B*bR-;CmU2xIm_U**!7?}NR2e&zpKsM~G zw3AU)tn|t*YMVP%3b>+- za0L*wr=Nb>GF!B;7hZeKuD$po^uk1nLu@I89UzipRhL|dKtg;9{Xv%uA%PrQT^G0p zn}GFeZ52A@TB+%ljk;q!?qeG_Zz3FgjuRbc;UXqNA^r1;)^u?;bRVrE>t3u3^F_$ug>qu{*L6~=<5Q8Z6rO7y#alQAmy zyE&wv-97riPmEa+_lSs#gu5L+XVFkGbSj}!@C$!qA+Q`Gj6!y#+}yJ1h1M6zb&9+g^p2UQkrd| zZ9Z&-P*bQ+JKZS@Y-KG$keBu8J$TM%n~88(vuTFSTeQ?xuHC>WOTre|3hDnWh;R0w zn&>T+27xF8P-&ob71s#_3ft;aB8#|lhl6e4pwsOl7=XKm-G@iOt5%e~ej6vhqqdaB zWIMX2Jl8w~Qmo7LE(9x;t}<4b)hiHyB(6!Umo;;aoz!oDje5dw%Sn4YsNZQ;L@3=@ zg;;Zr^f6Cc& zh)QU7?6G|Fm zTmW-n6zb#VDQ2K?<3^T)7e_8(hs6NMNU&wgOc$0m7lX5{Fd{y#ZN^Hy5TdL5b>CL% zh=pqBVjwC;LJUSm%M4qES4a|S6uslvV~(*^{5EyQbgNajj+3O+CW~F|+VyM$wjye) zT=5z;Y-HB?QvzF0J}(AlZD zLDf764X$RbAHuJ*_=l95>DC;VyKjG(VAln%c04MV%U6mS6PO$EEP@xXON0q};?d!@ zIxEkf`0q_YBU8O8)Hd&>l4h)7oPNZU10aW(C1i#YozquEG4P3*+OF_obu5C5#>Tl@ z!Z^P8(kP;G=1Y#D7GFo(7e#Q>|1eF9G60o3)J>I=HeL%D>eRb?H}YU7*cF$aYaf63 z2?loARsb&3k|++K<1K2pPAa!?ds@2?k=ubdObX&*GZ%xHw+4iM!!OebqH`i0h_!5t z0+ru9MSE6UptfPV%3}glvxkEv0Z4<`%qPeAr$0=x^DY`<4?OaSLzE)sK6d;Bf zJ2$!?@Qr_F#0Z-`XO7!!u3NUsrhGHrI_%$`_+;p0g<;u&ReJHpTrYz0NK7R?Ec0aH zuZwKu#!YtW3CCHVK7DWro6GJxg`hIAc3|6fsFcznlqpsR)l%&`bs(ZJ4vd2nHB*(w zOxFELFhuINUpq_)ZGb+-a9?rJj+-$qKEz3RL{^d<1#E$^<-;h5P{*+A&x65Jf~71( z)SJ;?OCpfZ*l!}@r92nns56)ET{|4Y{js)i$s*S_#kfy|U>6|~STKE#{W|GK=b4~( z%5!1<{NJoz-FnVSzb>8`^Vu0oO4GD?3m4-+R{f2eHf5d_y1pII{vcb6j=b9uN19wY zyRya_H*LbvxL9)K&AvEbJLKGR?1}sTXMWTNPEu7=PBnnmX=tq~096hQTAe0MZO**; zcI(~$v%0lXZSbJ8f%nc)tt0>w!4Uz*$HfMrzBp&c!iO-ufAM%l`UlM==AKF-^K;e0 z1$O^4PdI6f!j19cSf$&Jmg~Dzn zVnF7#AV`6gWHY0rKoAt>7~h0vv^i`h7&4(hj*m0#+emikg`R!=vKh#JP0n2{BH4QdAeL zfGe>Q&qF(FV#rmqc8wr|h}xnN3>bFpj^TALhX6RK3q;(_1B^;b6wNm=80rtb-GW-9 zkU1m+P4#6COwVdbm0&zX=z|PFz^42%6}`USe*9vbt%BkBdHi?`Y=g#&d5!>?4Ls{i z7XzYY>o(T+*b{6s%#_|CTLp=u8`r4~GsH7ePn4z5bcy?YjEU?RV5^)VYz`v)-p8Np ztld9&`(5<^wOs8|t;9+S4HH08DlOk}hfr!`cC5-6`}Wj=@I zot_u7mWVgb_;IhfsURqW;l?sImzTNz=z|psfhYq|q2Mf0Su%L$3<)4L@tZfSZw>3$ zvuqfEnutQd7xwT&!|mFuuC!Qod(Og2J2B}#BdLI(oIaO+#1Wcw-Igp1Yz`pOtZxMn z$@nJH1o@02;1!P;eeJR(_QESK0d=$bi1)Y7o&|wtZm{!pmeoSE zAlM|*O(T4UG2=mqtdHHh2z{~CW;bozQ{ul}HNaiP6SsT62eJjIU~%mr^sekJ#Rzrg zyg7v2o?xF7r{e9`N4wkdLJW@LKgc1F8EY?$dc|&n@hexMUJ-wQ4f9!G>HF1X%bRS2 zh77RvTXXHPr=GSWdmqIs7!SZwg7}ACtWeYmFh%p{{f0CJ)d(t!eY&^>&w3Q`$Dr0w zAH6*Kb%zhQsxlIQ1wTdqRyzcu3_v-DAT+5RqA5{TjCEq3BWX=wr;=|MpL4F$i~Dmi z?n&6s{z-iAd+r-%a|zYj263e`2F$@&P?kgv2T-%l)ye(q{V*lcv&*0<5mEEaxBbn= zkN?IdefzDY5*|3Pa$S%BtDO+wSOwG(Ap$9D=b7XH6eJcU;8PJ_z$5wDd6q=>!YvS* zw1W<@agRP?Q)bS#lTJR(CZh_7%fpZjCHaM?543a6Imd~aB?%ZYVuY z!Ze?J)*$P6*By4@m4C5%jq2M`M;~i>^A8(P zUYg*SuF{K55CdnSN48n2yNSRR=7KjJ#KZtsPg)V|fs6)&J#ckzWKCeun1`An0ToUR z%z?Ze60jeT+8|X4b5fEmKt{bz?b}+XLk_TWFTKFF;IjG!iF4L(+|1m_w|NVf*_zes zossC6w_ihoFb%g)f^pee*G~7YviyOGl+-I7n+vt`uQ%Oj9}wy8;}1WzKF1$hT%#N- zoEl0@eppGu+awLxOCp6G$Aljz+WX&5aFVRJ7++Rl zAn;A_f#}~zfIyT1sJv15vlfNKvn?fN?$_UPSFgZ|9{=+->+FJa&LcbBFni~nv3C7G zZnZ6|(eKJa-HA#=jq(;(<+X9QH3uMcj&`Um>`XITx3!nw8*dl?`Oo(1=rNWbyTMsu z$KV51h*q`UbN7fn=ngPQ!3)(~>3j>?^O?#OX7f z3!Ox$nS=ozJaB+D!PxAYtFExQOM=qJA^lFV)BE?cPKR~00*FifG{m%sg&!aGi1j&j zfDJhF9Q%3Vcx#Z9hX1vQ8HihBj8doy2>#zAUhHxoXw008-m(&hK<*LW4Z#(gI=p_|I@Jn}PrxFADA_k_|3g3Ib z#QTou>r6p9w2fK>Ie~Bx#)!M|`sN~Mv#3(%jWG@=V)ztDfs8TJXbC#vF&*IsuK7Wdn)9wPpOtsO>~aWE~e4`Ga??roFV z(i$|}&sM?&G_K7&)J4Z72|lzfqD!cK-bO`jXDsA`>O(y^;>DMp=a8R?QB)Lo8(GNO zi0;lGtZ{Ct{lWTNA>G~4vJ9d#st-a{J}I4v$#H${XsHmN0S$fU8wIfy0`u6)0EDoRg!RHLM55M`& zh7LK?9vk+c`H=$10pC}zfn~IAZfl4pn7w$R^9b-25=X#84#BEQ{tbzeOJ3ZQZ;SwN z_Mwsv56(fXhUwFl-`kFLuW|JmQc5)+G zHo!I_y@<8meU7#R4muF^*?!i#U0WB~QTJ+0+c$1t58idBoq+d5A>o;0FiwnNJbk+` z9(3*V=2LNJ_wqvsUVHge=yt}@@9iO36M{J~RveHxB30&dZqFKAj@Jh}f325J9Fz61 zH%o$0E!*3pPn916-sqLTrf3arQimpVFTmj}f3&_%Q5aA{xw=^N+#oA%CDA$lnB#2p zyJPLmx8AYyFTT*?Nd3v04-yK&v%HI2b(FJs#G8C-AVn&}XzH2ApRxuA9AuBbINEx3 z>1=}s54Fw9)>|q_vCr|x+2`XvF~3~J=s;z6!H1F2tZ7s2sQ#zf7GOK>>o4ty?mg_% z3odq&i6sk`*hS}^W&gSBE=$1$O}l)90n1&!()q9#qN`L=m{_*kN(5A}bg7*}4ummv z)2;tGm)YePUSLl=GtxHAoCi?}>X4=CaN9}^ZirFy5ZZR&_5i>$5}$jUN5>d&vqa@$ z_!Jc_5hlfI)v%WyddQ`JeRWhYV3fi$Cuq)ib#3>O;Dzmo|4#0!w97kdUpSH0Dk&Gy z*+uJlzh`e!{0heii1}itudzZpaAeocxUw==zWChwbU)Ivky0e%s#buaUKtnVc9|p& z&q*snE1GK>zXa}ck`B(2X(SS3;`ZBawWlEd{f_Br&y9G_&8r2o=h~u03+>l=bM5PI z#@m!>zt~qFkF$?B1STO~4QYc0jjS~WfD->VMAah#s`~lAZx+P=ib5HOozpuny=<%2 zZE(hs^!WoI>4^Wn*|FbetM}P?7AeC~8u5qF#e1yalZD$`BifsSg|ZUtBx3>W2f;{f z8y(*wR0mS*VsZf^67y!Qc z;d^%ZHCMaPRMO$(#hk#1S$rAT7x9VXVz}i>z#@`k%vNd=zjQ!w4Te57a{V-{=ty;eY z?;nyC@xHNdykgxtb+&@_8_Y)_DyQ<1oyX3K=9f3ec6QJ1uB&flE}HvdWdtWl01#%t zfdv#k9NP>@35IDy>`AQDf5Kp`>k-{Cs>9WbB4kAnp-XSBqhf1~9sTfwG3$5P}eApIom z^AWAk=ids#qJd%Xb(#2p`=)sd=+{tNz6`g`+ithDYgXAUq;by8+CaEgzmqNqDm%<3 zr}|WHaoyV0akrQScTF=TG+SUcO_>7e%pt)24O}%u&1(U4f0kz+qipKVK*F1P#s^KYB<<7DgB@o+a!d@inV*u;!j;4_asCW~_}lC;#u zb?ob}z9lsHJU7d^BMb12iP$dufg2_o6)ok2fR<_4QXR--zd+x$2YBt7r!9?LP*F~{ z6)DcQjG5R)%6Th?1R+QC?qQEU_9WgiS=N8xKoH0V7epn%R#8T5a`CE`;w@^&f`r-t zQj259T7<~dPx#qxy^gdQGk>-pepx_U3+(6^%t(J~0HEB|h}LhiKe zb_dIo;UI8?6nNsyEgfSjAy*e*TX7R&*bVD8+4(~U*_$7{Z|N{wTb3_lHmAfB-*bE!AQZ$jfNAT|_XG?%^X%RS9wmmrD|XT;r`UdN zT3a4^Arird!2W7>=f{o^n=$XulmyM@~(U5(!cNR zcdwr9&Y?LcF`O%IfSHL9W`bCC?$*uzHS8g)gD1cNga{sT$>p|U?RrZ~PsaPBkL9e- za>;^nfWJZoB@y2su0~DN1Oa>Y`R8oFS%V2Ry~-{XWl28gnMXx*xf9n$+~TQPsGxP#NRfBl=yTe{4tNx1qCj?XyUQVxG*CH73O ziUVzPTC5N^;4fIQ)NcCw&Gy&>ciNoaR$13> zN81B;-DAl$>se}Mrunh#j)iE%U_h47m=(Hl+g7OLhUVM9;vZw*^!SRToViX{cEVJue>g=i@=1pLe$5oD>W zy0>d*!yX=PLoc|%>D{H%pTBg8i$hR=N`_$8mfWndrL}8gt2boXO=Obn*yV7$@zy)7 zOQ#O@2@K)G|GCc!SFa^EMz*Cg7ktb&O?r3M@)Z-{7y(Ttm^}_3hazdl<`vpjY=dMU zB(*^nqJQBAv7oL&5^+U*f%#=E`Pr}(((J^#wQbVGiA3U@;25Xiin7Nez8ing21c<- zSqHv&Z3={1uL9B^207#4-ENTp6r~J?Z585VD#SJ-ks4ZpJ zEuCL{O~n7~aw`Le1=T3*;)xUg%!|(%Xw%L+v%lSP_dOO*{DA;50TL0k_~ero0|NHo z7*6~>CcrTQ>RYfN17I|Ruur6~F-UE;%$sfJKqOYq`q{d7>0o#L_aQsHS0DTC+aD}3 zqpA7oq+4taEc9Ul0!Vlq0+*ga(ge9F!iZe<=WFf5@5kF6|NSqH{`jpY5Z9k84w6wF9~yX^*}9hPBAduy4kFVDFB8 z!+IQ!xSl{nzRiS1rar%HHDu(WIi)r0ju38eB7Ht{mU!PYN{kooV49|-B!ME}{wPl3 zqn*E)?1(SH{(9Xtq*l+3deLOHqSkYLBqtC>v_v8VM75%&JP;^m1Y9Lo3ZRNz-Wq*h zr-Kf#B6QG6h|Q%FFHu+-l1}D9L^Im9x6}HcY>z(kylqBorbQ%Ow3A*6aj0m8Rci^g z1H$IQwBW8#1hHL@)Z(b4`q;2L(359n+f`Rxu46z^actF3%#xT#H!`0K0+cT_-XA;wE$++@|Ue7SQa z9D`-^TQ5HEGT!w&<4il|sAKGrXGYjsM7xO?B*qccB|u=JA_CSZE&@UF?HhJPSs-+Y zlIN{jVpC>JC#qr^zbDvMWrJy!VfPLj=HlC*d&XJTrbSEJuy`p_q_BSPsF~4gdj|o= zy(kxVKZvcE@=k{x>WGw}JcM-C%^Ekcsk7(fub*t6fBl7BaM`8SxkoR%|M8J_)G@tm z?CYcK?Kj@A1Mz^_yo$g*ix#ukvC~1NBx6^pliYmMe9^I^;(p_etZUuwXAbkn*(MaC zHqiX`QdP+|WS7OwZ7u%TkKSbhLY+m+S)ifgdma;$~iebtE zH9Zr)z#Sp+r31{rYsqTrUxF^W2D`!-^m>&mB_`$R(?$H}LpgE@O&Y4nMzf&kM$S}F(vM^aBpB1AqJsP^vG6=ad+7PH$id&EEdWgr5# z3n2MR&m)eo?&uY7K+mXMg?1s^2z}@w5whwm9#f#RV@4qK1jmt$Lu{S;cKub?LM(#} zP|g;R8Ddc<#i+#Y>A_H zL;L)jZ`@AvzW>~7r=Hl?-X8abz4Gd7R;O7D*N?mJyWi2Mn{T|yQji$a(T;{YRFt9EUS0Fe>F1jGqf zz*Gd8(C`N%@Us{gZ3cv|;6i@DlR-FZ1 z;;OX&bV(*jJx@W--Lw z&y@(!Ln7hrbngqlP>r8KR_dOyD;jX>$<`sW6`2iL_L6K!T2LWHFc#9JuxoR0f$^9% zhcv!i>V8BwE5smCzWuvrIJPk_uD;#KNVLP zbioio=N7iBcW{q(dYhLlwBv|f-mF1g`v-pK(jCVWZOjWG zqUA}V;=#p*g{>$g?Rv#1%a#Me?B2t;B_UGwvpdX&895AV@z3A;&_+J?u)Y26`6(4oKr%zVD zWelbxS}FztVoDW{LqKO7Q?SFxM}^e}m(^i+-A3@J0e0?yfmSqsffW*yBPO>18xY;g zFd)(LrebkpJO;50XR37V2%six+O(-1NJ{DgsT5G332%5wl8WCIX&>mb54A}ib`|kh z|36L^&8AHLF21 zh^lvsyD_E%Ath;NNpKJao0+zFi7AhGY~yD59rFSu5fOs%N*IyzE>+7}h!HC5W9KcA zwJlq0oew_1`t|7Uq5u*BrJT*8?+)V%$U#6CLU|K1GVCQ%y)Iw90nz)>a9xVx2Jx3| zg5by@1iD-1s|>9Za+B>ty!y;JK!i6&5SK$D2ol2~j~)CFj04BN|GwRQ^Np5@?T1=^ z+DRwcelSRdD^}QFufEEKq8Q5P(8hvC( z5Fk01xHlhZcNK9ncl8>?`of4#Xgik7NBNXsu}gnaeIez>exH z$2En`RUC<0gwD+)KEMXK1;SXy$i5(?W-CYamHsHnsVx=>Kt9sWPd^*SNm|0MA4et2hV*1o-Evn!O5&-Pn}QZJMQ0P3!|07h_`qkHvs zW^b3FPv1(q+Qd2-1ma`t;?;`4g)4cLM?P&A3?6EJ z2%_65m$fm_a+lPlm#v2UMav9-vC00W!dSxuLr9WoH}jvYN7 z;Jsor$dmxF;ASKdTNf;}RNC^_tFN|kW8by=Z@$59{_C~uG#6Vgdge4-|DJvHVaEh$ z&YUx7kkw-cx_LcGl|qb8@GQy`EtLlWKfHC4rI4~aM#iObYbBr$mU(=Kd9NZBjFLgc zLqylR@elU4P{D#CT=L_si#Q~eGw02*?|z=)gjKpuc{4hPgJT)Vf1?aQ`9>!V%>Qm2 zJNH&?GOb06MlPF|!p~|)=u(^Ru6`D|h-VCLNkv$g*KE|#j_7=tt;101-}ev0tWbXB z!4*}aDiMG0DDguzd|?M89epec`1~!KaKj54v6YMX7k5KMFvw)MOTgm;GAOQuxsZIJ z0eJ~zG?`EEAt!Muey)5UJmj|1TI8PTBp{(P-+k;HQ_%INAQ|w%4CO9gXot0FVOL-E ze^xsQQlFnqbU!2lFaf6zJk8oQs$;F|rrJqI9gQc*I=nvDK0s*@a+SITxr^wb5 zFr@P#huCSSoM_prS0N%!1fk0^b{9oE3>W|f{fS}a$ckMe-}BEs-%0!*eBu%NZPrYS z$G_a&sz0R>&@QU4(w`&=fDwp?_$ld*UxrN{QY>pj)LlnpA)dI?`8njj{Srxf1cqK1 z|1~0VqMsy6#7+W~Qo@82&$7OFZ=VY-Bah>e2$vnC4;T~?Q$Bmi65Pe`6DQD%KcDz= ze9l|C)ZQL7%D(ydQ_IBvJeMqm#0D%jVs!Qkd)tiY{d)}o?X+EiiI+eBj#MtYWd`^9 zt=Bz2fla}wlmn3#HOY?$&zik=o{H zyS70f$^dMGMOi*wsaY@mZ5xpI8OQg9PO*3)TwBp0DgfZlUC?+?ChH;^5Pj|PMLY`- zZ=Zh3Np^VKRℑ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 VyiXpD5rhB$002ovPDHLkV1g(dNk0Gp literal 0 HcmV?d00001 diff --git a/assets/2023-11-04-04-27-59.3d817820.png b/assets/2023-11-04-04-27-59.3d817820.png new file mode 100644 index 0000000000000000000000000000000000000000..3062da7dce5c2503dff93ec22f798983b99150c1 GIT binary patch literal 231697 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

  • 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�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 mFQ4J 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 d=C0d68HD{En4`C!bh7 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 U&9=4l_5c6?07*qoM6N<$f}jtZXaE2J literal 0 HcmV?d00001 diff --git a/assets/2023-11-04-05-01-04.fd5f8fb7.png b/assets/2023-11-04-05-01-04.fd5f8fb7.png new file mode 100644 index 0000000000000000000000000000000000000000..53e21c512b331ea936ce7409ad905c48e0d88b9a GIT binary patch literal 139482 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%0D^ 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 literal 0 HcmV?d00001 diff --git a/assets/academic_chemistry_index.md.ca0457b9.js b/assets/academic_chemistry_index.md.56f381d7.js similarity index 92% rename from assets/academic_chemistry_index.md.ca0457b9.js rename to assets/academic_chemistry_index.md.56f381d7.js index 465f6219..76a7aa17 100644 --- a/assets/academic_chemistry_index.md.ca0457b9.js +++ b/assets/academic_chemistry_index.md.56f381d7.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as c,c as r,H as s,k as e,a as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Welcome to Chemistry","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/index.md","filePath":"academic/chemistry/index.md","lastUpdated":1695377563000}'),m={name:"academic/chemistry/index.md"},n=e("h1",{id:"welcome-to-chemistry",tabindex:"-1"},[i("Welcome to Chemistry "),e("a",{class:"header-anchor",href:"#welcome-to-chemistry","aria-label":'Permalink to "Welcome to Chemistry"'},"​")],-1);function d(l,_,h,p,f,x){const t=a;return c(),r("div",null,[n,s(t,{readTime:"1",words:"3"})])}const N=o(m,[["render",d]]);export{k as __pageData,N as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as c,c as r,H as s,k as e,a as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Welcome to Chemistry","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/index.md","filePath":"academic/chemistry/index.md","lastUpdated":1699051935000}'),m={name:"academic/chemistry/index.md"},n=e("h1",{id:"welcome-to-chemistry",tabindex:"-1"},[i("Welcome to Chemistry "),e("a",{class:"header-anchor",href:"#welcome-to-chemistry","aria-label":'Permalink to "Welcome to Chemistry"'},"​")],-1);function d(l,_,h,p,f,x){const t=a;return c(),r("div",null,[n,s(t,{readTime:"1",words:"3"})])}const N=o(m,[["render",d]]);export{k as __pageData,N as default}; diff --git a/assets/academic_chemistry_index.md.ca0457b9.lean.js b/assets/academic_chemistry_index.md.56f381d7.lean.js similarity index 92% rename from assets/academic_chemistry_index.md.ca0457b9.lean.js rename to assets/academic_chemistry_index.md.56f381d7.lean.js index 465f6219..76a7aa17 100644 --- a/assets/academic_chemistry_index.md.ca0457b9.lean.js +++ b/assets/academic_chemistry_index.md.56f381d7.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as c,c as r,H as s,k as e,a as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Welcome to Chemistry","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/index.md","filePath":"academic/chemistry/index.md","lastUpdated":1695377563000}'),m={name:"academic/chemistry/index.md"},n=e("h1",{id:"welcome-to-chemistry",tabindex:"-1"},[i("Welcome to Chemistry "),e("a",{class:"header-anchor",href:"#welcome-to-chemistry","aria-label":'Permalink to "Welcome to Chemistry"'},"​")],-1);function d(l,_,h,p,f,x){const t=a;return c(),r("div",null,[n,s(t,{readTime:"1",words:"3"})])}const N=o(m,[["render",d]]);export{k as __pageData,N as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as c,c as r,H as s,k as e,a as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Welcome to Chemistry","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/index.md","filePath":"academic/chemistry/index.md","lastUpdated":1699051935000}'),m={name:"academic/chemistry/index.md"},n=e("h1",{id:"welcome-to-chemistry",tabindex:"-1"},[i("Welcome to Chemistry "),e("a",{class:"header-anchor",href:"#welcome-to-chemistry","aria-label":'Permalink to "Welcome to Chemistry"'},"​")],-1);function d(l,_,h,p,f,x){const t=a;return c(),r("div",null,[n,s(t,{readTime:"1",words:"3"})])}const N=o(m,[["render",d]]);export{k as __pageData,N as default}; diff --git a/assets/academic_chemistry_notes_12-5.md.4c698a37.js b/assets/academic_chemistry_notes_12-5.md.f9fc6ef4.js similarity index 99% rename from assets/academic_chemistry_notes_12-5.md.4c698a37.js rename to assets/academic_chemistry_notes_12-5.md.f9fc6ef4.js index 3519bb90..d2044508 100644 --- a/assets/academic_chemistry_notes_12-5.md.4c698a37.js +++ b/assets/academic_chemistry_notes_12-5.md.f9fc6ef4.js @@ -1 +1 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as n,c as m,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const cs=JSON.parse('{"title":"12-5: Reaction Mechanism","description":"","frontmatter":{"title":"12-5: Reaction Mechanism","editLink":true,"lastUpdated":true,"showArticleMetadata":true,"categories":["Chemistry"],"keywords":["chemistry","reaction","mechanism","reaction-mechanism","tutorial","explanation","textbook","reference"]},"headers":[],"relativePath":"academic/chemistry/notes/12-5.md","filePath":"academic/chemistry/notes/12-5.md","lastUpdated":1695377563000}'),r={name:"academic/chemistry/notes/12-5.md"},c=s("h1",{id:"_12-5-reaction-mechanism",tabindex:"-1"},[a("12-5: Reaction Mechanism "),s("a",{class:"header-anchor",href:"#_12-5-reaction-mechanism","aria-label":'Permalink to "12-5: Reaction Mechanism"'},"​")],-1),p=s("h2",{id:"_12-5-1-learning-objectives",tabindex:"-1"},[a("12-5-1: Learning Objectives "),s("a",{class:"header-anchor",href:"#_12-5-1-learning-objectives","aria-label":'Permalink to "12-5-1: Learning Objectives"'},"​")],-1),h=s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"Learning Objectives"),s("p",null,"One of the major reasons for studying chemical kinetics is to use measurements of the macroscopic properties of a system, such as the rate of change in the concentration of reactants or products with time, to discover the sequence of events that occur at the molecular level during a reaction. This molecular description is the mechanism of the reaction; it describes how individual atoms, ions, or molecules interact to form particular products. The stepwise changes are collectively called the reaction mechanism.")],-1),o=s("p",null,"In an internal combustion engine, for example, isooctane reacts with oxygen to give carbon dioxide and water:",-1),g=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"8")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"18")]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mn",null,"25"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"g")]),s("mo",{stretchy:"false"},")"),s("mo",null,"⟶"),s("mn",null,"16"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"g")]),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"O"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{C}_{8} \\mathrm{H}_{18}(\\mathrm{l})+25 \\mathrm{O}_{2}(\\mathrm{~g}) \\longrightarrow 16 \\mathrm{CO}_{2}(\\mathrm{~g})+18 \\mathrm{H}_{2} \\mathrm{O}(\\mathrm{g}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"8")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"18")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"25"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⟶"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"16"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"18"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathrm"},"O"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),u=s("p",null,"For this reaction to occur in a single step, 25 dioxygen molecules and 2 isooctane molecules would have to collide simultaneously and be converted to 34 molecules of product, which is very unlikely. It is more likely that a complex series of reactions takes place in a stepwise fashion. Each individual reaction, which is called an elementary reaction, involves one, two, or (rarely) three atoms, molecules, or ions. The overall sequence of elementary reactions is the mechanism of the reaction. The sum of the individual steps, or elementary reactions, in the mechanism must give the balanced chemical equation for the overall reaction.",-1),d=s("p",null,"The overall sequence of elementary reactions is the mechanism of the reaction.",-1),v=s("h2",{id:"_12-5-2-molecularity-and-the-rate-determining-step",tabindex:"-1"},[a("12-5-2: Molecularity and the Rate-Determining Step "),s("a",{class:"header-anchor",href:"#_12-5-2-molecularity-and-the-rate-determining-step","aria-label":'Permalink to "12-5-2: Molecularity and the Rate-Determining Step"'},"​")],-1),y=s("p",null,"To demonstrate how the analysis of elementary reactions helps us determine the overall reaction mechanism, we will examine the much simpler reaction of carbon monoxide with nitrogen dioxide.",-1),w=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O"),s("mo",null,"+"),s("mn",null,"2"),s("mi",{mathvariant:"normal"},"N"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",null,"→"),s("mn",null,"2"),s("mi",{mathvariant:"normal"},"C"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{2CO + 2NO_2 \\rightarrow 2CO_2 + N_2O_4} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"2CO"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"2N"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"2C"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"4")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])])],-1),x=s("p",null,[a("From the balanced chemical equation, one might expect the reaction to occur via a collision of one molecule of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with a molecule of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" that results in the transfer of an oxygen atom from nitrogen to carbon. The experimentally determined rate law for the reaction, however, is as follows:")],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_{2}\\right]^{2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])])],-1),k=s("p",null,[a("The fact that the reaction is second order in "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\left[\\mathrm{NO}_{2}\\right]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),a(" and independent of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"[\\mathrm{CO}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]")])])]),a(" tells us that it does not occur by the simple collision model outlined previously. If it did, its predicted rate law would be")],-1),f=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_{2}\\right][\\mathrm{CO}] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),z=s("p",null,"The following two-step mechanism is consistent with the rate law if step 1 is much slower than step 2:",-1),O=s("h3",{id:"_15-2-1-two-step-mechanism",tabindex:"-1"},[a("15-2-1: Two-Step Mechanism "),s("a",{class:"header-anchor",href:"#_15-2-1-two-step-mechanism","aria-label":'Permalink to "15-2-1: Two-Step Mechanism"'},"​")],-1),_=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Steps"),s("th",null,"Reaction"),s("th",null,"Reaction Type")])]),s("tbody",null,[s("tr",null,[s("td",null,"step 1"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"⟶")]),s("mtext",null," slow ")])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}+\\mathrm{NO}_{2} \\stackrel{\\text { slow }}{\\longrightarrow} \\mathrm{NO}_{3}+\\mathrm{NO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.4471em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2971em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"⟶")])]),s("span",{style:{top:"-3.711em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"}," slow ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.011em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")])])])])]),s("td",null,"elementary reaction")]),s("tr",null,[s("td",null,"step 2"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("munder",{accentunder:"true"},[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"→"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("mo",{stretchy:"true"},"‾")])]),s("annotation",{encoding:"application/x-tex"},"\\underline{\\mathrm{NO}_{3}+\\mathrm{CO} \\rightarrow \\mathrm{NO}_{2}+\\mathrm{CO}_{2}}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0333em","vertical-align":"-0.35em"}}),s("span",{class:"mord underline"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6833em"}},[s("span",{style:{top:"-2.69em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"underline-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.35em"}},[s("span")])])])])])])])]),s("td",null,"elementary reaction")]),s("tr",null,[s("td",null,"sum"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"→"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}+\\mathrm{CO} \\rightarrow \\mathrm{NO}+\\mathrm{CO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,"overall reaction")])])],-1),M=s("p",null,[a("According to this mechanism, the overall reaction occurs in two steps, or elementary reactions. Summing steps 1 and 2 and canceling on both sides of the equation gives the overall balanced chemical equation for the reaction. The "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO_3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),a(" molecule is intermediate in the reaction, a species that does not appear in the balanced chemical equation for the overall reaction. It is formed as a product of the first step but is consumed in the second step.")],-1),N=s("p",null,"The sum of the elementary reactions in a reaction mechanism must give the overall balanced chemical equation of the reaction.",-1),C=s("h2",{id:"_12-5-3-using-molecularity-to-describe-a-rate-law",tabindex:"-1"},[a("12-5-3: Using Molecularity to Describe a Rate Law "),s("a",{class:"header-anchor",href:"#_12-5-3-using-molecularity-to-describe-a-rate-law","aria-label":'Permalink to "12-5-3: Using Molecularity to Describe a Rate Law"'},"​")],-1),L=s("p",null,"The molecularity of an elementary reaction is the number of molecules that collide during that step in the mechanism. If there is only a single reactant molecule in an elementary reaction, that step is designated as unimolecular; if there are two reactant molecules, it is bimolecular; and if there are three reactant molecules (a relatively rare situation), it is termolecular. Elementary reactions that involve the simultaneous collision of more than three molecules are highly improbable and have never been observed experimentally. (To understand why, try to make three or more marbles or pool balls collide with one another simultaneously!)",-1),A=s("div",{class:"warning custom-block"},[s("p",{class:"custom-block-title"},"About the image"),s("p",null,"The Basis for Writing Rate Laws of Elementary Reactions. This diagram illustrates how the number of possible collisions per unit time between two reactant species, A and B, depends on the number of A and B particles present. The number of collisions between A and B particles increases as the product of the number of particles, not as the sum. This is why the rate law for an elementary reaction depends on the product of the concentrations of the species that collide in that step. (CC BY-NC-SA; anonymous)")],-1),B=s("p",null,[a("Writing the rate law for an elementary reaction is straightforward because we know how many molecules must collide simultaneously for the elementary reaction to occur; hence the order of the elementary reaction is the same as its molecularity (Table 14.6.1). In contrast, the rate law for the reaction cannot be determined from the balanced chemical equation for the overall reaction. The general rate law for a unimolecular elementary reaction ( "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"→")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A} \\rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→")])])]),a(" products) is")],-1),T=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mi",null,"A"),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[A] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),R=s("p",null,[a("For bimolecular reactions, the reaction rate depends on the number of collisions per unit time, which is proportional to the product of the concentrations of the reactants, as shown in Figure 14.6.1 For a bimolecular elementary reaction of the form "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B} \\rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→")])])]),a(" products, the general rate law is")],-1),I=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mi",null,"A"),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",null,"B"),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[A][B] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),q=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Elementary Reaction"),s("th",null,"Molecularity"),s("th",null,"Rate"),s("th",null,"Reaction Order")])]),s("tbody",null,[s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Unimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]")])])])]),s("td",null,"first")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"2\\mathrm{~A} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Bimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),s("td",null,"second")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Bimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}][\\mathrm{B}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mclose"},"]")])])])]),s("td",null,"second")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{~A}+\\mathrm{B} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Termolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"B")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]^2[\\mathrm{~B}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"B")]),s("span",{class:"mclose"},"]")])])])]),s("td",null,"third")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"C"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B}+\\mathrm{C} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Termolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"C"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}][\\mathrm{B}][\\mathrm{C}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mclose"},"]")])])])]),s("td",null,"third")])])],-1),S=s("blockquote",null,[s("p",null,"For elementary reactions, the order of the elementary reaction is the same as its molecularity. In contrast, the rate law cannot be determined from the balanced chemical equation for the overall reaction (unless it is a single step mechanism and is therefore also an elementary step).")],-1),P=s("h2",{id:"_12-5-4-identifying-the-rate-determining-step",tabindex:"-1"},[a("12-5-4: Identifying the Rate-Determining Step "),s("a",{class:"header-anchor",href:"#_12-5-4-identifying-the-rate-determining-step","aria-label":'Permalink to "12-5-4: Identifying the Rate-Determining Step"'},"​")],-1),D=s("p",null,"Note the important difference between writing rate laws for elementary reactions and the balanced chemical equation of the overall reaction. Because the balanced chemical equation does not necessarily reveal the individual elementary reactions by which the reaction occurs, we cannot obtain the rate law for a reaction from the overall balanced chemical equation alone. In fact, it is the rate law for the slowest overall reaction, which is the same as the rate law for the slowest step in the reaction mechanism, the ratedetermining step, that must give the experimentally determined rate law for the overall reaction.This statement is true if one step is substantially slower than all the others, typically by a factor of 10 or more. If two or more slow steps have comparable rates, the experimentally determined rate laws can become complex. Our discussion is limited to reactions in which one step can be identified as being substantially slower than any other. The reason for this is that any process that occurs through a sequence of steps can take place no faster than the slowest step in the sequence. In an automotive assembly line, for example, a component cannot be used faster than it is produced. Similarly, blood pressure is regulated by the flow of blood through the smallest passages, the capillaries. Because movement through capillaries constitutes the rate-determining step in blood flow, blood pressure can be regulated by medications that cause the capillaries to contract or dilate. A chemical reaction that occurs via a series of elementary reactions can take place no faster than the slowest step in the series of reactions.",-1),H=s("p",null,"Look at the rate laws for each elementary reaction in the example as well as for the overall reaction.",-1),E=s("p",null,"Rate laws for each elementary reaction in our example as well as for the overall reaction",-1),F=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Steps"),s("th",null,"Reaction"),s("th",null,"Rate")])]),s("tbody",null,[s("tr",null,[s("td",null,"step 1"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("msub",null,[s("mi",{mathvariant:"normal"},"k"),s("mn",null,"1")])])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_2+\\mathrm{NO}_2 \\stackrel{\\mathrm{k}_1}{\\rightarrow} \\mathrm{NO}_3+\\mathrm{NO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.3141em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.578em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mtext",null," predicted) ")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k_1\\left[\\mathrm{NO}_2\\right]^2(\\text { predicted) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," predicted) ")])])])])])]),s("tr",null,[s("td",null,"step 2"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("munder",{accentunder:"true"},[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")])])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("mo",{stretchy:"true"},"‾")])]),s("annotation",{encoding:"application/x-tex"},"\\underline{\\mathrm{NO}_3+\\mathrm{CO} \\stackrel{k_2}{\\rightarrow} \\mathrm{NO}_2+\\mathrm{CO}_2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.5141em","vertical-align":"-0.35em"}}),s("span",{class:"mord underline"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-2.8541em"}},[s("span",{class:"pstrut",style:{height:"3.1641em"}}),s("span",{class:"underline-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.1641em"}},[s("span",{class:"pstrut",style:{height:"3.1641em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.578em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.35em"}},[s("span")])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"("),s("mtext",null," predicted "),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k_2\\left[\\mathrm{NO}_3\\right][\\mathrm{CO}](\\text { predicted })")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," predicted ")]),s("span",{class:"mclose"},")")])])])])]),s("tr",null,[s("td",null,"step 3"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("mi",null,"k")])]),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_2+\\mathrm{CO} \\stackrel{k}{\\rightarrow} \\mathrm{NO}+\\mathrm{CO}_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.153em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.153em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.5669em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mtext",null," observed) ")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_2\\right]^2(\\text { observed) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," observed) ")])])])])])])])],-1),j=s("p",null,[a("The experimentally determined rate law for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"C"),s("mi",null,"O")]),s("annotation",{encoding:"application/x-tex"},"C O")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"CO")])])]),a(" is the same as the predicted rate law for step 1 . This tells us that the first elementary reaction is the rate-determining step, so "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(" for the overall reaction must equal "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},"k_{1}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". That is, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" is formed slowly in step 1, but once it is formed, it reacts very rapidly with CO in step 2.")],-1),U=s("p",null,"Sometimes chemists are able to propose two or more mechanisms that are consistent with the available data. If a proposed mechanism predicts the wrong experimental rate law, however, the mechanism must be incorrect.",-1),$=s("h3",{id:"_12-5-4-1-example-a-reaction-with-an-intermediate",tabindex:"-1"},[a("12-5-4-1: Example-A Reaction with an Intermediate "),s("a",{class:"header-anchor",href:"#_12-5-4-1-example-a-reaction-with-an-intermediate","aria-label":'Permalink to "12-5-4-1: Example-A Reaction with an Intermediate"'},"​")],-1),V=s("p",null,[a("In an alternative mechanism for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" appearing as an intermediate.")],-1),W=s("p",null,[a("alternative mechanism for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" appearing as an intermediate.")],-1),G=s("p",null,[a("Write the rate law for each elementary reaction. Is this mechanism consistent with the experimentally determined rate law (rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mrow",null,[s("mi",{mathvariant:"normal"},"k"),s("mo",{stretchy:"false"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"t")])]),s("annotation",{encoding:"application/x-tex"},"=\\mathrm{k[{NO}_{2}]^{2}t}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])])])])])])]),s("span",{class:"mord mathrm"},"t")])])])]),a(")")],-1),J=s("p",null,"Given: elementary reactions Asked for: rate law for each elementary reaction and overall rate law",-1),Y=s("h4",{id:"strategy",tabindex:"-1"},[a("Strategy "),s("a",{class:"header-anchor",href:"#strategy","aria-label":'Permalink to "Strategy"'},"​")],-1),K=s("ul",null,[s("li",null,[s("p",null,"Determine the rate law for each elementary reaction in the reaction.")]),s("li",null,[s("p",null,"Determine which rate law corresponds to the experimentally determined rate law for the reaction. This rate law is the one for the rate-determining step.")])],-1),Q=s("h4",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),X=s("details",{class:"details custom-block"},[s("summary",null,"View solution"),s("p",null,[a("A The rate law for step 1 is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"=k_{1}\\left[\\mathrm{NO}_{2}\\right]^{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a("; for step 2 , it is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"N")]),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"=k_{2}\\left[\\mathrm{~N}_{2} \\mathrm{O}_{4}\\right][\\mathrm{CO}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"N")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]")])])]),a(".")]),s("p",null,[a("B If step 1 is slow (and therefore the rate-determining step), then the overall rate law for the reaction will be the same: rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"k_{1}\\left[\\mathrm{NO}_{2}\\right]^{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a(". This is the same as the experimentally determined rate law. Hence this mechanism, with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as an intermediate, and the one described previously, with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as an intermediate, are kinetically indistinguishable. In this case, further experiments are needed to distinguish between them. For example, the researcher could try to detect the proposed intermediates, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(", directly.")])],-1);function Z(ss,as,ts,ls,es,ns){const t=l;return n(),m("div",null,[c,i(t,{readTime:"11",words:"1.9k"}),p,h,o,g,u,d,v,y,w,x,b,k,f,z,O,_,M,N,C,L,A,B,T,R,I,q,S,P,D,H,E,F,j,U,$,V,W,G,J,Y,K,Q,X])}const ps=e(r,[["render",Z]]);export{cs as __pageData,ps as default}; +import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as n,c as m,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const cs=JSON.parse('{"title":"12-5: Reaction Mechanism","description":"","frontmatter":{"title":"12-5: Reaction Mechanism","editLink":true,"lastUpdated":true,"showArticleMetadata":true,"categories":["Chemistry"],"keywords":["chemistry","reaction","mechanism","reaction-mechanism","tutorial","explanation","textbook","reference"]},"headers":[],"relativePath":"academic/chemistry/notes/12-5.md","filePath":"academic/chemistry/notes/12-5.md","lastUpdated":1699051935000}'),r={name:"academic/chemistry/notes/12-5.md"},c=s("h1",{id:"_12-5-reaction-mechanism",tabindex:"-1"},[a("12-5: Reaction Mechanism "),s("a",{class:"header-anchor",href:"#_12-5-reaction-mechanism","aria-label":'Permalink to "12-5: Reaction Mechanism"'},"​")],-1),p=s("h2",{id:"_12-5-1-learning-objectives",tabindex:"-1"},[a("12-5-1: Learning Objectives "),s("a",{class:"header-anchor",href:"#_12-5-1-learning-objectives","aria-label":'Permalink to "12-5-1: Learning Objectives"'},"​")],-1),h=s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"Learning Objectives"),s("p",null,"One of the major reasons for studying chemical kinetics is to use measurements of the macroscopic properties of a system, such as the rate of change in the concentration of reactants or products with time, to discover the sequence of events that occur at the molecular level during a reaction. This molecular description is the mechanism of the reaction; it describes how individual atoms, ions, or molecules interact to form particular products. The stepwise changes are collectively called the reaction mechanism.")],-1),o=s("p",null,"In an internal combustion engine, for example, isooctane reacts with oxygen to give carbon dioxide and water:",-1),g=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"8")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"18")]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mn",null,"25"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"g")]),s("mo",{stretchy:"false"},")"),s("mo",null,"⟶"),s("mn",null,"16"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"g")]),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"O"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{C}_{8} \\mathrm{H}_{18}(\\mathrm{l})+25 \\mathrm{O}_{2}(\\mathrm{~g}) \\longrightarrow 16 \\mathrm{CO}_{2}(\\mathrm{~g})+18 \\mathrm{H}_{2} \\mathrm{O}(\\mathrm{g}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"8")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"18")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"25"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⟶"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"16"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"18"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathrm"},"O"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),u=s("p",null,"For this reaction to occur in a single step, 25 dioxygen molecules and 2 isooctane molecules would have to collide simultaneously and be converted to 34 molecules of product, which is very unlikely. It is more likely that a complex series of reactions takes place in a stepwise fashion. Each individual reaction, which is called an elementary reaction, involves one, two, or (rarely) three atoms, molecules, or ions. The overall sequence of elementary reactions is the mechanism of the reaction. The sum of the individual steps, or elementary reactions, in the mechanism must give the balanced chemical equation for the overall reaction.",-1),d=s("p",null,"The overall sequence of elementary reactions is the mechanism of the reaction.",-1),v=s("h2",{id:"_12-5-2-molecularity-and-the-rate-determining-step",tabindex:"-1"},[a("12-5-2: Molecularity and the Rate-Determining Step "),s("a",{class:"header-anchor",href:"#_12-5-2-molecularity-and-the-rate-determining-step","aria-label":'Permalink to "12-5-2: Molecularity and the Rate-Determining Step"'},"​")],-1),y=s("p",null,"To demonstrate how the analysis of elementary reactions helps us determine the overall reaction mechanism, we will examine the much simpler reaction of carbon monoxide with nitrogen dioxide.",-1),w=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O"),s("mo",null,"+"),s("mn",null,"2"),s("mi",{mathvariant:"normal"},"N"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",null,"→"),s("mn",null,"2"),s("mi",{mathvariant:"normal"},"C"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{2CO + 2NO_2 \\rightarrow 2CO_2 + N_2O_4} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"2CO"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"2N"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"2C"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"4")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])])],-1),x=s("p",null,[a("From the balanced chemical equation, one might expect the reaction to occur via a collision of one molecule of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with a molecule of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" that results in the transfer of an oxygen atom from nitrogen to carbon. The experimentally determined rate law for the reaction, however, is as follows:")],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_{2}\\right]^{2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])])],-1),k=s("p",null,[a("The fact that the reaction is second order in "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\left[\\mathrm{NO}_{2}\\right]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),a(" and independent of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"[\\mathrm{CO}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]")])])]),a(" tells us that it does not occur by the simple collision model outlined previously. If it did, its predicted rate law would be")],-1),f=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_{2}\\right][\\mathrm{CO}] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),z=s("p",null,"The following two-step mechanism is consistent with the rate law if step 1 is much slower than step 2:",-1),O=s("h3",{id:"_15-2-1-two-step-mechanism",tabindex:"-1"},[a("15-2-1: Two-Step Mechanism "),s("a",{class:"header-anchor",href:"#_15-2-1-two-step-mechanism","aria-label":'Permalink to "15-2-1: Two-Step Mechanism"'},"​")],-1),_=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Steps"),s("th",null,"Reaction"),s("th",null,"Reaction Type")])]),s("tbody",null,[s("tr",null,[s("td",null,"step 1"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"⟶")]),s("mtext",null," slow ")])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}+\\mathrm{NO}_{2} \\stackrel{\\text { slow }}{\\longrightarrow} \\mathrm{NO}_{3}+\\mathrm{NO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.4471em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2971em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"⟶")])]),s("span",{style:{top:"-3.711em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"}," slow ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.011em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")])])])])]),s("td",null,"elementary reaction")]),s("tr",null,[s("td",null,"step 2"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("munder",{accentunder:"true"},[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"→"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("mo",{stretchy:"true"},"‾")])]),s("annotation",{encoding:"application/x-tex"},"\\underline{\\mathrm{NO}_{3}+\\mathrm{CO} \\rightarrow \\mathrm{NO}_{2}+\\mathrm{CO}_{2}}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0333em","vertical-align":"-0.35em"}}),s("span",{class:"mord underline"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6833em"}},[s("span",{style:{top:"-2.69em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"underline-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.35em"}},[s("span")])])])])])])])]),s("td",null,"elementary reaction")]),s("tr",null,[s("td",null,"sum"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"→"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}+\\mathrm{CO} \\rightarrow \\mathrm{NO}+\\mathrm{CO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,"overall reaction")])])],-1),M=s("p",null,[a("According to this mechanism, the overall reaction occurs in two steps, or elementary reactions. Summing steps 1 and 2 and canceling on both sides of the equation gives the overall balanced chemical equation for the reaction. The "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO_3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),a(" molecule is intermediate in the reaction, a species that does not appear in the balanced chemical equation for the overall reaction. It is formed as a product of the first step but is consumed in the second step.")],-1),N=s("p",null,"The sum of the elementary reactions in a reaction mechanism must give the overall balanced chemical equation of the reaction.",-1),C=s("h2",{id:"_12-5-3-using-molecularity-to-describe-a-rate-law",tabindex:"-1"},[a("12-5-3: Using Molecularity to Describe a Rate Law "),s("a",{class:"header-anchor",href:"#_12-5-3-using-molecularity-to-describe-a-rate-law","aria-label":'Permalink to "12-5-3: Using Molecularity to Describe a Rate Law"'},"​")],-1),L=s("p",null,"The molecularity of an elementary reaction is the number of molecules that collide during that step in the mechanism. If there is only a single reactant molecule in an elementary reaction, that step is designated as unimolecular; if there are two reactant molecules, it is bimolecular; and if there are three reactant molecules (a relatively rare situation), it is termolecular. Elementary reactions that involve the simultaneous collision of more than three molecules are highly improbable and have never been observed experimentally. (To understand why, try to make three or more marbles or pool balls collide with one another simultaneously!)",-1),A=s("div",{class:"warning custom-block"},[s("p",{class:"custom-block-title"},"About the image"),s("p",null,"The Basis for Writing Rate Laws of Elementary Reactions. This diagram illustrates how the number of possible collisions per unit time between two reactant species, A and B, depends on the number of A and B particles present. The number of collisions between A and B particles increases as the product of the number of particles, not as the sum. This is why the rate law for an elementary reaction depends on the product of the concentrations of the species that collide in that step. (CC BY-NC-SA; anonymous)")],-1),B=s("p",null,[a("Writing the rate law for an elementary reaction is straightforward because we know how many molecules must collide simultaneously for the elementary reaction to occur; hence the order of the elementary reaction is the same as its molecularity (Table 14.6.1). In contrast, the rate law for the reaction cannot be determined from the balanced chemical equation for the overall reaction. The general rate law for a unimolecular elementary reaction ( "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"→")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A} \\rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→")])])]),a(" products) is")],-1),T=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mi",null,"A"),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[A] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),R=s("p",null,[a("For bimolecular reactions, the reaction rate depends on the number of collisions per unit time, which is proportional to the product of the concentrations of the reactants, as shown in Figure 14.6.1 For a bimolecular elementary reaction of the form "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B} \\rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→")])])]),a(" products, the general rate law is")],-1),I=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mi",null,"A"),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",null,"B"),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[A][B] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),q=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Elementary Reaction"),s("th",null,"Molecularity"),s("th",null,"Rate"),s("th",null,"Reaction Order")])]),s("tbody",null,[s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Unimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]")])])])]),s("td",null,"first")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"2\\mathrm{~A} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Bimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),s("td",null,"second")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Bimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}][\\mathrm{B}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mclose"},"]")])])])]),s("td",null,"second")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{~A}+\\mathrm{B} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Termolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"B")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]^2[\\mathrm{~B}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"B")]),s("span",{class:"mclose"},"]")])])])]),s("td",null,"third")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"C"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B}+\\mathrm{C} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Termolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"C"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}][\\mathrm{B}][\\mathrm{C}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mclose"},"]")])])])]),s("td",null,"third")])])],-1),S=s("blockquote",null,[s("p",null,"For elementary reactions, the order of the elementary reaction is the same as its molecularity. In contrast, the rate law cannot be determined from the balanced chemical equation for the overall reaction (unless it is a single step mechanism and is therefore also an elementary step).")],-1),P=s("h2",{id:"_12-5-4-identifying-the-rate-determining-step",tabindex:"-1"},[a("12-5-4: Identifying the Rate-Determining Step "),s("a",{class:"header-anchor",href:"#_12-5-4-identifying-the-rate-determining-step","aria-label":'Permalink to "12-5-4: Identifying the Rate-Determining Step"'},"​")],-1),D=s("p",null,"Note the important difference between writing rate laws for elementary reactions and the balanced chemical equation of the overall reaction. Because the balanced chemical equation does not necessarily reveal the individual elementary reactions by which the reaction occurs, we cannot obtain the rate law for a reaction from the overall balanced chemical equation alone. In fact, it is the rate law for the slowest overall reaction, which is the same as the rate law for the slowest step in the reaction mechanism, the ratedetermining step, that must give the experimentally determined rate law for the overall reaction.This statement is true if one step is substantially slower than all the others, typically by a factor of 10 or more. If two or more slow steps have comparable rates, the experimentally determined rate laws can become complex. Our discussion is limited to reactions in which one step can be identified as being substantially slower than any other. The reason for this is that any process that occurs through a sequence of steps can take place no faster than the slowest step in the sequence. In an automotive assembly line, for example, a component cannot be used faster than it is produced. Similarly, blood pressure is regulated by the flow of blood through the smallest passages, the capillaries. Because movement through capillaries constitutes the rate-determining step in blood flow, blood pressure can be regulated by medications that cause the capillaries to contract or dilate. A chemical reaction that occurs via a series of elementary reactions can take place no faster than the slowest step in the series of reactions.",-1),H=s("p",null,"Look at the rate laws for each elementary reaction in the example as well as for the overall reaction.",-1),E=s("p",null,"Rate laws for each elementary reaction in our example as well as for the overall reaction",-1),F=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Steps"),s("th",null,"Reaction"),s("th",null,"Rate")])]),s("tbody",null,[s("tr",null,[s("td",null,"step 1"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("msub",null,[s("mi",{mathvariant:"normal"},"k"),s("mn",null,"1")])])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_2+\\mathrm{NO}_2 \\stackrel{\\mathrm{k}_1}{\\rightarrow} \\mathrm{NO}_3+\\mathrm{NO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.3141em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.578em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mtext",null," predicted) ")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k_1\\left[\\mathrm{NO}_2\\right]^2(\\text { predicted) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," predicted) ")])])])])])]),s("tr",null,[s("td",null,"step 2"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("munder",{accentunder:"true"},[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")])])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("mo",{stretchy:"true"},"‾")])]),s("annotation",{encoding:"application/x-tex"},"\\underline{\\mathrm{NO}_3+\\mathrm{CO} \\stackrel{k_2}{\\rightarrow} \\mathrm{NO}_2+\\mathrm{CO}_2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.5141em","vertical-align":"-0.35em"}}),s("span",{class:"mord underline"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-2.8541em"}},[s("span",{class:"pstrut",style:{height:"3.1641em"}}),s("span",{class:"underline-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.1641em"}},[s("span",{class:"pstrut",style:{height:"3.1641em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.578em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.35em"}},[s("span")])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"("),s("mtext",null," predicted "),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k_2\\left[\\mathrm{NO}_3\\right][\\mathrm{CO}](\\text { predicted })")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," predicted ")]),s("span",{class:"mclose"},")")])])])])]),s("tr",null,[s("td",null,"step 3"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("mi",null,"k")])]),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_2+\\mathrm{CO} \\stackrel{k}{\\rightarrow} \\mathrm{NO}+\\mathrm{CO}_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.153em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.153em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.5669em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mtext",null," observed) ")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_2\\right]^2(\\text { observed) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," observed) ")])])])])])])])],-1),j=s("p",null,[a("The experimentally determined rate law for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"C"),s("mi",null,"O")]),s("annotation",{encoding:"application/x-tex"},"C O")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"CO")])])]),a(" is the same as the predicted rate law for step 1 . This tells us that the first elementary reaction is the rate-determining step, so "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(" for the overall reaction must equal "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},"k_{1}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". That is, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" is formed slowly in step 1, but once it is formed, it reacts very rapidly with CO in step 2.")],-1),U=s("p",null,"Sometimes chemists are able to propose two or more mechanisms that are consistent with the available data. If a proposed mechanism predicts the wrong experimental rate law, however, the mechanism must be incorrect.",-1),$=s("h3",{id:"_12-5-4-1-example-a-reaction-with-an-intermediate",tabindex:"-1"},[a("12-5-4-1: Example-A Reaction with an Intermediate "),s("a",{class:"header-anchor",href:"#_12-5-4-1-example-a-reaction-with-an-intermediate","aria-label":'Permalink to "12-5-4-1: Example-A Reaction with an Intermediate"'},"​")],-1),V=s("p",null,[a("In an alternative mechanism for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" appearing as an intermediate.")],-1),W=s("p",null,[a("alternative mechanism for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" appearing as an intermediate.")],-1),G=s("p",null,[a("Write the rate law for each elementary reaction. Is this mechanism consistent with the experimentally determined rate law (rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mrow",null,[s("mi",{mathvariant:"normal"},"k"),s("mo",{stretchy:"false"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"t")])]),s("annotation",{encoding:"application/x-tex"},"=\\mathrm{k[{NO}_{2}]^{2}t}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])])])])])])]),s("span",{class:"mord mathrm"},"t")])])])]),a(")")],-1),J=s("p",null,"Given: elementary reactions Asked for: rate law for each elementary reaction and overall rate law",-1),Y=s("h4",{id:"strategy",tabindex:"-1"},[a("Strategy "),s("a",{class:"header-anchor",href:"#strategy","aria-label":'Permalink to "Strategy"'},"​")],-1),K=s("ul",null,[s("li",null,[s("p",null,"Determine the rate law for each elementary reaction in the reaction.")]),s("li",null,[s("p",null,"Determine which rate law corresponds to the experimentally determined rate law for the reaction. This rate law is the one for the rate-determining step.")])],-1),Q=s("h4",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),X=s("details",{class:"details custom-block"},[s("summary",null,"View solution"),s("p",null,[a("A The rate law for step 1 is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"=k_{1}\\left[\\mathrm{NO}_{2}\\right]^{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a("; for step 2 , it is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"N")]),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"=k_{2}\\left[\\mathrm{~N}_{2} \\mathrm{O}_{4}\\right][\\mathrm{CO}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"N")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]")])])]),a(".")]),s("p",null,[a("B If step 1 is slow (and therefore the rate-determining step), then the overall rate law for the reaction will be the same: rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"k_{1}\\left[\\mathrm{NO}_{2}\\right]^{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a(". This is the same as the experimentally determined rate law. Hence this mechanism, with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as an intermediate, and the one described previously, with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as an intermediate, are kinetically indistinguishable. In this case, further experiments are needed to distinguish between them. For example, the researcher could try to detect the proposed intermediates, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(", directly.")])],-1);function Z(ss,as,ts,ls,es,ns){const t=l;return n(),m("div",null,[c,i(t,{readTime:"11",words:"1.9k"}),p,h,o,g,u,d,v,y,w,x,b,k,f,z,O,_,M,N,C,L,A,B,T,R,I,q,S,P,D,H,E,F,j,U,$,V,W,G,J,Y,K,Q,X])}const ps=e(r,[["render",Z]]);export{cs as __pageData,ps as default}; diff --git a/assets/academic_chemistry_notes_12-5.md.4c698a37.lean.js b/assets/academic_chemistry_notes_12-5.md.f9fc6ef4.lean.js similarity index 99% rename from assets/academic_chemistry_notes_12-5.md.4c698a37.lean.js rename to assets/academic_chemistry_notes_12-5.md.f9fc6ef4.lean.js index 3519bb90..d2044508 100644 --- a/assets/academic_chemistry_notes_12-5.md.4c698a37.lean.js +++ b/assets/academic_chemistry_notes_12-5.md.f9fc6ef4.lean.js @@ -1 +1 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as n,c as m,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const cs=JSON.parse('{"title":"12-5: Reaction Mechanism","description":"","frontmatter":{"title":"12-5: Reaction Mechanism","editLink":true,"lastUpdated":true,"showArticleMetadata":true,"categories":["Chemistry"],"keywords":["chemistry","reaction","mechanism","reaction-mechanism","tutorial","explanation","textbook","reference"]},"headers":[],"relativePath":"academic/chemistry/notes/12-5.md","filePath":"academic/chemistry/notes/12-5.md","lastUpdated":1695377563000}'),r={name:"academic/chemistry/notes/12-5.md"},c=s("h1",{id:"_12-5-reaction-mechanism",tabindex:"-1"},[a("12-5: Reaction Mechanism "),s("a",{class:"header-anchor",href:"#_12-5-reaction-mechanism","aria-label":'Permalink to "12-5: Reaction Mechanism"'},"​")],-1),p=s("h2",{id:"_12-5-1-learning-objectives",tabindex:"-1"},[a("12-5-1: Learning Objectives "),s("a",{class:"header-anchor",href:"#_12-5-1-learning-objectives","aria-label":'Permalink to "12-5-1: Learning Objectives"'},"​")],-1),h=s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"Learning Objectives"),s("p",null,"One of the major reasons for studying chemical kinetics is to use measurements of the macroscopic properties of a system, such as the rate of change in the concentration of reactants or products with time, to discover the sequence of events that occur at the molecular level during a reaction. This molecular description is the mechanism of the reaction; it describes how individual atoms, ions, or molecules interact to form particular products. The stepwise changes are collectively called the reaction mechanism.")],-1),o=s("p",null,"In an internal combustion engine, for example, isooctane reacts with oxygen to give carbon dioxide and water:",-1),g=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"8")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"18")]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mn",null,"25"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"g")]),s("mo",{stretchy:"false"},")"),s("mo",null,"⟶"),s("mn",null,"16"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"g")]),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"O"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{C}_{8} \\mathrm{H}_{18}(\\mathrm{l})+25 \\mathrm{O}_{2}(\\mathrm{~g}) \\longrightarrow 16 \\mathrm{CO}_{2}(\\mathrm{~g})+18 \\mathrm{H}_{2} \\mathrm{O}(\\mathrm{g}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"8")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"18")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"25"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⟶"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"16"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"18"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathrm"},"O"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),u=s("p",null,"For this reaction to occur in a single step, 25 dioxygen molecules and 2 isooctane molecules would have to collide simultaneously and be converted to 34 molecules of product, which is very unlikely. It is more likely that a complex series of reactions takes place in a stepwise fashion. Each individual reaction, which is called an elementary reaction, involves one, two, or (rarely) three atoms, molecules, or ions. The overall sequence of elementary reactions is the mechanism of the reaction. The sum of the individual steps, or elementary reactions, in the mechanism must give the balanced chemical equation for the overall reaction.",-1),d=s("p",null,"The overall sequence of elementary reactions is the mechanism of the reaction.",-1),v=s("h2",{id:"_12-5-2-molecularity-and-the-rate-determining-step",tabindex:"-1"},[a("12-5-2: Molecularity and the Rate-Determining Step "),s("a",{class:"header-anchor",href:"#_12-5-2-molecularity-and-the-rate-determining-step","aria-label":'Permalink to "12-5-2: Molecularity and the Rate-Determining Step"'},"​")],-1),y=s("p",null,"To demonstrate how the analysis of elementary reactions helps us determine the overall reaction mechanism, we will examine the much simpler reaction of carbon monoxide with nitrogen dioxide.",-1),w=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O"),s("mo",null,"+"),s("mn",null,"2"),s("mi",{mathvariant:"normal"},"N"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",null,"→"),s("mn",null,"2"),s("mi",{mathvariant:"normal"},"C"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{2CO + 2NO_2 \\rightarrow 2CO_2 + N_2O_4} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"2CO"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"2N"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"2C"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"4")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])])],-1),x=s("p",null,[a("From the balanced chemical equation, one might expect the reaction to occur via a collision of one molecule of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with a molecule of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" that results in the transfer of an oxygen atom from nitrogen to carbon. The experimentally determined rate law for the reaction, however, is as follows:")],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_{2}\\right]^{2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])])],-1),k=s("p",null,[a("The fact that the reaction is second order in "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\left[\\mathrm{NO}_{2}\\right]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),a(" and independent of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"[\\mathrm{CO}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]")])])]),a(" tells us that it does not occur by the simple collision model outlined previously. If it did, its predicted rate law would be")],-1),f=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_{2}\\right][\\mathrm{CO}] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),z=s("p",null,"The following two-step mechanism is consistent with the rate law if step 1 is much slower than step 2:",-1),O=s("h3",{id:"_15-2-1-two-step-mechanism",tabindex:"-1"},[a("15-2-1: Two-Step Mechanism "),s("a",{class:"header-anchor",href:"#_15-2-1-two-step-mechanism","aria-label":'Permalink to "15-2-1: Two-Step Mechanism"'},"​")],-1),_=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Steps"),s("th",null,"Reaction"),s("th",null,"Reaction Type")])]),s("tbody",null,[s("tr",null,[s("td",null,"step 1"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"⟶")]),s("mtext",null," slow ")])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}+\\mathrm{NO}_{2} \\stackrel{\\text { slow }}{\\longrightarrow} \\mathrm{NO}_{3}+\\mathrm{NO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.4471em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2971em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"⟶")])]),s("span",{style:{top:"-3.711em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"}," slow ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.011em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")])])])])]),s("td",null,"elementary reaction")]),s("tr",null,[s("td",null,"step 2"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("munder",{accentunder:"true"},[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"→"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("mo",{stretchy:"true"},"‾")])]),s("annotation",{encoding:"application/x-tex"},"\\underline{\\mathrm{NO}_{3}+\\mathrm{CO} \\rightarrow \\mathrm{NO}_{2}+\\mathrm{CO}_{2}}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0333em","vertical-align":"-0.35em"}}),s("span",{class:"mord underline"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6833em"}},[s("span",{style:{top:"-2.69em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"underline-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.35em"}},[s("span")])])])])])])])]),s("td",null,"elementary reaction")]),s("tr",null,[s("td",null,"sum"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"→"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}+\\mathrm{CO} \\rightarrow \\mathrm{NO}+\\mathrm{CO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,"overall reaction")])])],-1),M=s("p",null,[a("According to this mechanism, the overall reaction occurs in two steps, or elementary reactions. Summing steps 1 and 2 and canceling on both sides of the equation gives the overall balanced chemical equation for the reaction. The "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO_3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),a(" molecule is intermediate in the reaction, a species that does not appear in the balanced chemical equation for the overall reaction. It is formed as a product of the first step but is consumed in the second step.")],-1),N=s("p",null,"The sum of the elementary reactions in a reaction mechanism must give the overall balanced chemical equation of the reaction.",-1),C=s("h2",{id:"_12-5-3-using-molecularity-to-describe-a-rate-law",tabindex:"-1"},[a("12-5-3: Using Molecularity to Describe a Rate Law "),s("a",{class:"header-anchor",href:"#_12-5-3-using-molecularity-to-describe-a-rate-law","aria-label":'Permalink to "12-5-3: Using Molecularity to Describe a Rate Law"'},"​")],-1),L=s("p",null,"The molecularity of an elementary reaction is the number of molecules that collide during that step in the mechanism. If there is only a single reactant molecule in an elementary reaction, that step is designated as unimolecular; if there are two reactant molecules, it is bimolecular; and if there are three reactant molecules (a relatively rare situation), it is termolecular. Elementary reactions that involve the simultaneous collision of more than three molecules are highly improbable and have never been observed experimentally. (To understand why, try to make three or more marbles or pool balls collide with one another simultaneously!)",-1),A=s("div",{class:"warning custom-block"},[s("p",{class:"custom-block-title"},"About the image"),s("p",null,"The Basis for Writing Rate Laws of Elementary Reactions. This diagram illustrates how the number of possible collisions per unit time between two reactant species, A and B, depends on the number of A and B particles present. The number of collisions between A and B particles increases as the product of the number of particles, not as the sum. This is why the rate law for an elementary reaction depends on the product of the concentrations of the species that collide in that step. (CC BY-NC-SA; anonymous)")],-1),B=s("p",null,[a("Writing the rate law for an elementary reaction is straightforward because we know how many molecules must collide simultaneously for the elementary reaction to occur; hence the order of the elementary reaction is the same as its molecularity (Table 14.6.1). In contrast, the rate law for the reaction cannot be determined from the balanced chemical equation for the overall reaction. The general rate law for a unimolecular elementary reaction ( "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"→")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A} \\rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→")])])]),a(" products) is")],-1),T=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mi",null,"A"),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[A] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),R=s("p",null,[a("For bimolecular reactions, the reaction rate depends on the number of collisions per unit time, which is proportional to the product of the concentrations of the reactants, as shown in Figure 14.6.1 For a bimolecular elementary reaction of the form "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B} \\rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→")])])]),a(" products, the general rate law is")],-1),I=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mi",null,"A"),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",null,"B"),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[A][B] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),q=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Elementary Reaction"),s("th",null,"Molecularity"),s("th",null,"Rate"),s("th",null,"Reaction Order")])]),s("tbody",null,[s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Unimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]")])])])]),s("td",null,"first")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"2\\mathrm{~A} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Bimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),s("td",null,"second")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Bimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}][\\mathrm{B}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mclose"},"]")])])])]),s("td",null,"second")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{~A}+\\mathrm{B} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Termolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"B")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]^2[\\mathrm{~B}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"B")]),s("span",{class:"mclose"},"]")])])])]),s("td",null,"third")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"C"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B}+\\mathrm{C} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Termolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"C"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}][\\mathrm{B}][\\mathrm{C}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mclose"},"]")])])])]),s("td",null,"third")])])],-1),S=s("blockquote",null,[s("p",null,"For elementary reactions, the order of the elementary reaction is the same as its molecularity. In contrast, the rate law cannot be determined from the balanced chemical equation for the overall reaction (unless it is a single step mechanism and is therefore also an elementary step).")],-1),P=s("h2",{id:"_12-5-4-identifying-the-rate-determining-step",tabindex:"-1"},[a("12-5-4: Identifying the Rate-Determining Step "),s("a",{class:"header-anchor",href:"#_12-5-4-identifying-the-rate-determining-step","aria-label":'Permalink to "12-5-4: Identifying the Rate-Determining Step"'},"​")],-1),D=s("p",null,"Note the important difference between writing rate laws for elementary reactions and the balanced chemical equation of the overall reaction. Because the balanced chemical equation does not necessarily reveal the individual elementary reactions by which the reaction occurs, we cannot obtain the rate law for a reaction from the overall balanced chemical equation alone. In fact, it is the rate law for the slowest overall reaction, which is the same as the rate law for the slowest step in the reaction mechanism, the ratedetermining step, that must give the experimentally determined rate law for the overall reaction.This statement is true if one step is substantially slower than all the others, typically by a factor of 10 or more. If two or more slow steps have comparable rates, the experimentally determined rate laws can become complex. Our discussion is limited to reactions in which one step can be identified as being substantially slower than any other. The reason for this is that any process that occurs through a sequence of steps can take place no faster than the slowest step in the sequence. In an automotive assembly line, for example, a component cannot be used faster than it is produced. Similarly, blood pressure is regulated by the flow of blood through the smallest passages, the capillaries. Because movement through capillaries constitutes the rate-determining step in blood flow, blood pressure can be regulated by medications that cause the capillaries to contract or dilate. A chemical reaction that occurs via a series of elementary reactions can take place no faster than the slowest step in the series of reactions.",-1),H=s("p",null,"Look at the rate laws for each elementary reaction in the example as well as for the overall reaction.",-1),E=s("p",null,"Rate laws for each elementary reaction in our example as well as for the overall reaction",-1),F=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Steps"),s("th",null,"Reaction"),s("th",null,"Rate")])]),s("tbody",null,[s("tr",null,[s("td",null,"step 1"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("msub",null,[s("mi",{mathvariant:"normal"},"k"),s("mn",null,"1")])])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_2+\\mathrm{NO}_2 \\stackrel{\\mathrm{k}_1}{\\rightarrow} \\mathrm{NO}_3+\\mathrm{NO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.3141em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.578em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mtext",null," predicted) ")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k_1\\left[\\mathrm{NO}_2\\right]^2(\\text { predicted) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," predicted) ")])])])])])]),s("tr",null,[s("td",null,"step 2"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("munder",{accentunder:"true"},[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")])])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("mo",{stretchy:"true"},"‾")])]),s("annotation",{encoding:"application/x-tex"},"\\underline{\\mathrm{NO}_3+\\mathrm{CO} \\stackrel{k_2}{\\rightarrow} \\mathrm{NO}_2+\\mathrm{CO}_2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.5141em","vertical-align":"-0.35em"}}),s("span",{class:"mord underline"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-2.8541em"}},[s("span",{class:"pstrut",style:{height:"3.1641em"}}),s("span",{class:"underline-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.1641em"}},[s("span",{class:"pstrut",style:{height:"3.1641em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.578em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.35em"}},[s("span")])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"("),s("mtext",null," predicted "),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k_2\\left[\\mathrm{NO}_3\\right][\\mathrm{CO}](\\text { predicted })")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," predicted ")]),s("span",{class:"mclose"},")")])])])])]),s("tr",null,[s("td",null,"step 3"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("mi",null,"k")])]),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_2+\\mathrm{CO} \\stackrel{k}{\\rightarrow} \\mathrm{NO}+\\mathrm{CO}_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.153em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.153em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.5669em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mtext",null," observed) ")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_2\\right]^2(\\text { observed) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," observed) ")])])])])])])])],-1),j=s("p",null,[a("The experimentally determined rate law for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"C"),s("mi",null,"O")]),s("annotation",{encoding:"application/x-tex"},"C O")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"CO")])])]),a(" is the same as the predicted rate law for step 1 . This tells us that the first elementary reaction is the rate-determining step, so "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(" for the overall reaction must equal "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},"k_{1}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". That is, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" is formed slowly in step 1, but once it is formed, it reacts very rapidly with CO in step 2.")],-1),U=s("p",null,"Sometimes chemists are able to propose two or more mechanisms that are consistent with the available data. If a proposed mechanism predicts the wrong experimental rate law, however, the mechanism must be incorrect.",-1),$=s("h3",{id:"_12-5-4-1-example-a-reaction-with-an-intermediate",tabindex:"-1"},[a("12-5-4-1: Example-A Reaction with an Intermediate "),s("a",{class:"header-anchor",href:"#_12-5-4-1-example-a-reaction-with-an-intermediate","aria-label":'Permalink to "12-5-4-1: Example-A Reaction with an Intermediate"'},"​")],-1),V=s("p",null,[a("In an alternative mechanism for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" appearing as an intermediate.")],-1),W=s("p",null,[a("alternative mechanism for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" appearing as an intermediate.")],-1),G=s("p",null,[a("Write the rate law for each elementary reaction. Is this mechanism consistent with the experimentally determined rate law (rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mrow",null,[s("mi",{mathvariant:"normal"},"k"),s("mo",{stretchy:"false"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"t")])]),s("annotation",{encoding:"application/x-tex"},"=\\mathrm{k[{NO}_{2}]^{2}t}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])])])])])])]),s("span",{class:"mord mathrm"},"t")])])])]),a(")")],-1),J=s("p",null,"Given: elementary reactions Asked for: rate law for each elementary reaction and overall rate law",-1),Y=s("h4",{id:"strategy",tabindex:"-1"},[a("Strategy "),s("a",{class:"header-anchor",href:"#strategy","aria-label":'Permalink to "Strategy"'},"​")],-1),K=s("ul",null,[s("li",null,[s("p",null,"Determine the rate law for each elementary reaction in the reaction.")]),s("li",null,[s("p",null,"Determine which rate law corresponds to the experimentally determined rate law for the reaction. This rate law is the one for the rate-determining step.")])],-1),Q=s("h4",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),X=s("details",{class:"details custom-block"},[s("summary",null,"View solution"),s("p",null,[a("A The rate law for step 1 is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"=k_{1}\\left[\\mathrm{NO}_{2}\\right]^{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a("; for step 2 , it is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"N")]),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"=k_{2}\\left[\\mathrm{~N}_{2} \\mathrm{O}_{4}\\right][\\mathrm{CO}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"N")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]")])])]),a(".")]),s("p",null,[a("B If step 1 is slow (and therefore the rate-determining step), then the overall rate law for the reaction will be the same: rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"k_{1}\\left[\\mathrm{NO}_{2}\\right]^{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a(". This is the same as the experimentally determined rate law. Hence this mechanism, with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as an intermediate, and the one described previously, with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as an intermediate, are kinetically indistinguishable. In this case, further experiments are needed to distinguish between them. For example, the researcher could try to detect the proposed intermediates, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(", directly.")])],-1);function Z(ss,as,ts,ls,es,ns){const t=l;return n(),m("div",null,[c,i(t,{readTime:"11",words:"1.9k"}),p,h,o,g,u,d,v,y,w,x,b,k,f,z,O,_,M,N,C,L,A,B,T,R,I,q,S,P,D,H,E,F,j,U,$,V,W,G,J,Y,K,Q,X])}const ps=e(r,[["render",Z]]);export{cs as __pageData,ps as default}; +import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as n,c as m,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const cs=JSON.parse('{"title":"12-5: Reaction Mechanism","description":"","frontmatter":{"title":"12-5: Reaction Mechanism","editLink":true,"lastUpdated":true,"showArticleMetadata":true,"categories":["Chemistry"],"keywords":["chemistry","reaction","mechanism","reaction-mechanism","tutorial","explanation","textbook","reference"]},"headers":[],"relativePath":"academic/chemistry/notes/12-5.md","filePath":"academic/chemistry/notes/12-5.md","lastUpdated":1699051935000}'),r={name:"academic/chemistry/notes/12-5.md"},c=s("h1",{id:"_12-5-reaction-mechanism",tabindex:"-1"},[a("12-5: Reaction Mechanism "),s("a",{class:"header-anchor",href:"#_12-5-reaction-mechanism","aria-label":'Permalink to "12-5: Reaction Mechanism"'},"​")],-1),p=s("h2",{id:"_12-5-1-learning-objectives",tabindex:"-1"},[a("12-5-1: Learning Objectives "),s("a",{class:"header-anchor",href:"#_12-5-1-learning-objectives","aria-label":'Permalink to "12-5-1: Learning Objectives"'},"​")],-1),h=s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"Learning Objectives"),s("p",null,"One of the major reasons for studying chemical kinetics is to use measurements of the macroscopic properties of a system, such as the rate of change in the concentration of reactants or products with time, to discover the sequence of events that occur at the molecular level during a reaction. This molecular description is the mechanism of the reaction; it describes how individual atoms, ions, or molecules interact to form particular products. The stepwise changes are collectively called the reaction mechanism.")],-1),o=s("p",null,"In an internal combustion engine, for example, isooctane reacts with oxygen to give carbon dioxide and water:",-1),g=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"8")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"18")]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mn",null,"25"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"g")]),s("mo",{stretchy:"false"},")"),s("mo",null,"⟶"),s("mn",null,"16"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"g")]),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"O"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{C}_{8} \\mathrm{H}_{18}(\\mathrm{l})+25 \\mathrm{O}_{2}(\\mathrm{~g}) \\longrightarrow 16 \\mathrm{CO}_{2}(\\mathrm{~g})+18 \\mathrm{H}_{2} \\mathrm{O}(\\mathrm{g}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"8")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"18")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"25"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⟶"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"16"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"18"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathrm"},"O"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),u=s("p",null,"For this reaction to occur in a single step, 25 dioxygen molecules and 2 isooctane molecules would have to collide simultaneously and be converted to 34 molecules of product, which is very unlikely. It is more likely that a complex series of reactions takes place in a stepwise fashion. Each individual reaction, which is called an elementary reaction, involves one, two, or (rarely) three atoms, molecules, or ions. The overall sequence of elementary reactions is the mechanism of the reaction. The sum of the individual steps, or elementary reactions, in the mechanism must give the balanced chemical equation for the overall reaction.",-1),d=s("p",null,"The overall sequence of elementary reactions is the mechanism of the reaction.",-1),v=s("h2",{id:"_12-5-2-molecularity-and-the-rate-determining-step",tabindex:"-1"},[a("12-5-2: Molecularity and the Rate-Determining Step "),s("a",{class:"header-anchor",href:"#_12-5-2-molecularity-and-the-rate-determining-step","aria-label":'Permalink to "12-5-2: Molecularity and the Rate-Determining Step"'},"​")],-1),y=s("p",null,"To demonstrate how the analysis of elementary reactions helps us determine the overall reaction mechanism, we will examine the much simpler reaction of carbon monoxide with nitrogen dioxide.",-1),w=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O"),s("mo",null,"+"),s("mn",null,"2"),s("mi",{mathvariant:"normal"},"N"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",null,"→"),s("mn",null,"2"),s("mi",{mathvariant:"normal"},"C"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{2CO + 2NO_2 \\rightarrow 2CO_2 + N_2O_4} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"2CO"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"2N"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"2C"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"4")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])])],-1),x=s("p",null,[a("From the balanced chemical equation, one might expect the reaction to occur via a collision of one molecule of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with a molecule of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" that results in the transfer of an oxygen atom from nitrogen to carbon. The experimentally determined rate law for the reaction, however, is as follows:")],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_{2}\\right]^{2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])])],-1),k=s("p",null,[a("The fact that the reaction is second order in "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\left[\\mathrm{NO}_{2}\\right]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),a(" and independent of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"[\\mathrm{CO}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]")])])]),a(" tells us that it does not occur by the simple collision model outlined previously. If it did, its predicted rate law would be")],-1),f=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_{2}\\right][\\mathrm{CO}] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),z=s("p",null,"The following two-step mechanism is consistent with the rate law if step 1 is much slower than step 2:",-1),O=s("h3",{id:"_15-2-1-two-step-mechanism",tabindex:"-1"},[a("15-2-1: Two-Step Mechanism "),s("a",{class:"header-anchor",href:"#_15-2-1-two-step-mechanism","aria-label":'Permalink to "15-2-1: Two-Step Mechanism"'},"​")],-1),_=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Steps"),s("th",null,"Reaction"),s("th",null,"Reaction Type")])]),s("tbody",null,[s("tr",null,[s("td",null,"step 1"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"⟶")]),s("mtext",null," slow ")])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}+\\mathrm{NO}_{2} \\stackrel{\\text { slow }}{\\longrightarrow} \\mathrm{NO}_{3}+\\mathrm{NO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.4471em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2971em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"⟶")])]),s("span",{style:{top:"-3.711em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"}," slow ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.011em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")])])])])]),s("td",null,"elementary reaction")]),s("tr",null,[s("td",null,"step 2"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("munder",{accentunder:"true"},[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"→"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("mo",{stretchy:"true"},"‾")])]),s("annotation",{encoding:"application/x-tex"},"\\underline{\\mathrm{NO}_{3}+\\mathrm{CO} \\rightarrow \\mathrm{NO}_{2}+\\mathrm{CO}_{2}}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0333em","vertical-align":"-0.35em"}}),s("span",{class:"mord underline"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6833em"}},[s("span",{style:{top:"-2.69em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"underline-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.35em"}},[s("span")])])])])])])])]),s("td",null,"elementary reaction")]),s("tr",null,[s("td",null,"sum"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"→"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}+\\mathrm{CO} \\rightarrow \\mathrm{NO}+\\mathrm{CO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,"overall reaction")])])],-1),M=s("p",null,[a("According to this mechanism, the overall reaction occurs in two steps, or elementary reactions. Summing steps 1 and 2 and canceling on both sides of the equation gives the overall balanced chemical equation for the reaction. The "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO_3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),a(" molecule is intermediate in the reaction, a species that does not appear in the balanced chemical equation for the overall reaction. It is formed as a product of the first step but is consumed in the second step.")],-1),N=s("p",null,"The sum of the elementary reactions in a reaction mechanism must give the overall balanced chemical equation of the reaction.",-1),C=s("h2",{id:"_12-5-3-using-molecularity-to-describe-a-rate-law",tabindex:"-1"},[a("12-5-3: Using Molecularity to Describe a Rate Law "),s("a",{class:"header-anchor",href:"#_12-5-3-using-molecularity-to-describe-a-rate-law","aria-label":'Permalink to "12-5-3: Using Molecularity to Describe a Rate Law"'},"​")],-1),L=s("p",null,"The molecularity of an elementary reaction is the number of molecules that collide during that step in the mechanism. If there is only a single reactant molecule in an elementary reaction, that step is designated as unimolecular; if there are two reactant molecules, it is bimolecular; and if there are three reactant molecules (a relatively rare situation), it is termolecular. Elementary reactions that involve the simultaneous collision of more than three molecules are highly improbable and have never been observed experimentally. (To understand why, try to make three or more marbles or pool balls collide with one another simultaneously!)",-1),A=s("div",{class:"warning custom-block"},[s("p",{class:"custom-block-title"},"About the image"),s("p",null,"The Basis for Writing Rate Laws of Elementary Reactions. This diagram illustrates how the number of possible collisions per unit time between two reactant species, A and B, depends on the number of A and B particles present. The number of collisions between A and B particles increases as the product of the number of particles, not as the sum. This is why the rate law for an elementary reaction depends on the product of the concentrations of the species that collide in that step. (CC BY-NC-SA; anonymous)")],-1),B=s("p",null,[a("Writing the rate law for an elementary reaction is straightforward because we know how many molecules must collide simultaneously for the elementary reaction to occur; hence the order of the elementary reaction is the same as its molecularity (Table 14.6.1). In contrast, the rate law for the reaction cannot be determined from the balanced chemical equation for the overall reaction. The general rate law for a unimolecular elementary reaction ( "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"→")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A} \\rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→")])])]),a(" products) is")],-1),T=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mi",null,"A"),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[A] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),R=s("p",null,[a("For bimolecular reactions, the reaction rate depends on the number of collisions per unit time, which is proportional to the product of the concentrations of the reactants, as shown in Figure 14.6.1 For a bimolecular elementary reaction of the form "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B} \\rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→")])])]),a(" products, the general rate law is")],-1),I=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mi",null,"A"),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",null,"B"),s("mo",{stretchy:"false"},"]"),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[A][B] . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mclose"},"]"),s("span",{class:"mord"},".")])])])])],-1),q=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Elementary Reaction"),s("th",null,"Molecularity"),s("th",null,"Rate"),s("th",null,"Reaction Order")])]),s("tbody",null,[s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Unimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]")])])])]),s("td",null,"first")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"2\\mathrm{~A} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Bimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),s("td",null,"second")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Bimolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}][\\mathrm{B}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mclose"},"]")])])])]),s("td",null,"second")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{~A}+\\mathrm{B} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Termolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"B")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}]^2[\\mathrm{~B}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"B")]),s("span",{class:"mclose"},"]")])])])]),s("td",null,"third")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"A"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"B"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"C"),s("mo",null,"→"),s("mtext",null," products ")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{A}+\\mathrm{B}+\\mathrm{C} \\rightarrow \\text { products }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," products ")])])])])]),s("td",null,"Termolecular"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"C"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k[\\mathrm{~A}][\\mathrm{B}][\\mathrm{C}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"B"),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"["),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mclose"},"]")])])])]),s("td",null,"third")])])],-1),S=s("blockquote",null,[s("p",null,"For elementary reactions, the order of the elementary reaction is the same as its molecularity. In contrast, the rate law cannot be determined from the balanced chemical equation for the overall reaction (unless it is a single step mechanism and is therefore also an elementary step).")],-1),P=s("h2",{id:"_12-5-4-identifying-the-rate-determining-step",tabindex:"-1"},[a("12-5-4: Identifying the Rate-Determining Step "),s("a",{class:"header-anchor",href:"#_12-5-4-identifying-the-rate-determining-step","aria-label":'Permalink to "12-5-4: Identifying the Rate-Determining Step"'},"​")],-1),D=s("p",null,"Note the important difference between writing rate laws for elementary reactions and the balanced chemical equation of the overall reaction. Because the balanced chemical equation does not necessarily reveal the individual elementary reactions by which the reaction occurs, we cannot obtain the rate law for a reaction from the overall balanced chemical equation alone. In fact, it is the rate law for the slowest overall reaction, which is the same as the rate law for the slowest step in the reaction mechanism, the ratedetermining step, that must give the experimentally determined rate law for the overall reaction.This statement is true if one step is substantially slower than all the others, typically by a factor of 10 or more. If two or more slow steps have comparable rates, the experimentally determined rate laws can become complex. Our discussion is limited to reactions in which one step can be identified as being substantially slower than any other. The reason for this is that any process that occurs through a sequence of steps can take place no faster than the slowest step in the sequence. In an automotive assembly line, for example, a component cannot be used faster than it is produced. Similarly, blood pressure is regulated by the flow of blood through the smallest passages, the capillaries. Because movement through capillaries constitutes the rate-determining step in blood flow, blood pressure can be regulated by medications that cause the capillaries to contract or dilate. A chemical reaction that occurs via a series of elementary reactions can take place no faster than the slowest step in the series of reactions.",-1),H=s("p",null,"Look at the rate laws for each elementary reaction in the example as well as for the overall reaction.",-1),E=s("p",null,"Rate laws for each elementary reaction in our example as well as for the overall reaction",-1),F=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Steps"),s("th",null,"Reaction"),s("th",null,"Rate")])]),s("tbody",null,[s("tr",null,[s("td",null,"step 1"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("msub",null,[s("mi",{mathvariant:"normal"},"k"),s("mn",null,"1")])])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_2+\\mathrm{NO}_2 \\stackrel{\\mathrm{k}_1}{\\rightarrow} \\mathrm{NO}_3+\\mathrm{NO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.3141em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.578em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mtext",null," predicted) ")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k_1\\left[\\mathrm{NO}_2\\right]^2(\\text { predicted) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," predicted) ")])])])])])]),s("tr",null,[s("td",null,"step 2"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("munder",{accentunder:"true"},[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")])])]),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("mo",{stretchy:"true"},"‾")])]),s("annotation",{encoding:"application/x-tex"},"\\underline{\\mathrm{NO}_3+\\mathrm{CO} \\stackrel{k_2}{\\rightarrow} \\mathrm{NO}_2+\\mathrm{CO}_2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.5141em","vertical-align":"-0.35em"}}),s("span",{class:"mord underline"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-2.8541em"}},[s("span",{class:"pstrut",style:{height:"3.1641em"}}),s("span",{class:"underline-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.1641em"}},[s("span",{class:"pstrut",style:{height:"3.1641em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1641em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.578em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.35em"}},[s("span")])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]"),s("mo",{stretchy:"false"},"("),s("mtext",null," predicted "),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k_2\\left[\\mathrm{NO}_3\\right][\\mathrm{CO}](\\text { predicted })")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]"),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," predicted ")]),s("span",{class:"mclose"},")")])])])])]),s("tr",null,[s("td",null,"step 3"),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",null,"+"),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,[s("mover",null,[s("mo",null,[s("mo",null,"→")]),s("mi",null,"k")])]),s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mo",null,"+"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_2+\\mathrm{CO} \\stackrel{k}{\\rightarrow} \\mathrm{NO}+\\mathrm{CO}_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.153em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.153em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",null,[s("span",{class:"mop"},"→")])]),s("span",{style:{top:"-3.5669em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mi",null,"k"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mtext",null," observed) ")]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=k\\left[\\mathrm{NO}_2\\right]^2(\\text { observed) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord text"},[s("span",{class:"mord"}," observed) ")])])])])])])])],-1),j=s("p",null,[a("The experimentally determined rate law for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"C"),s("mi",null,"O")]),s("annotation",{encoding:"application/x-tex"},"C O")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"CO")])])]),a(" is the same as the predicted rate law for step 1 . This tells us that the first elementary reaction is the rate-determining step, so "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(" for the overall reaction must equal "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},"k_{1}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". That is, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" is formed slowly in step 1, but once it is formed, it reacts very rapidly with CO in step 2.")],-1),U=s("p",null,"Sometimes chemists are able to propose two or more mechanisms that are consistent with the available data. If a proposed mechanism predicts the wrong experimental rate law, however, the mechanism must be incorrect.",-1),$=s("h3",{id:"_12-5-4-1-example-a-reaction-with-an-intermediate",tabindex:"-1"},[a("12-5-4-1: Example-A Reaction with an Intermediate "),s("a",{class:"header-anchor",href:"#_12-5-4-1-example-a-reaction-with-an-intermediate","aria-label":'Permalink to "12-5-4-1: Example-A Reaction with an Intermediate"'},"​")],-1),V=s("p",null,[a("In an alternative mechanism for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" appearing as an intermediate.")],-1),W=s("p",null,[a("alternative mechanism for the reaction of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{CO}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")])])])]),a(" with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" appearing as an intermediate.")],-1),G=s("p",null,[a("Write the rate law for each elementary reaction. Is this mechanism consistent with the experimentally determined rate law (rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mrow",null,[s("mi",{mathvariant:"normal"},"k"),s("mo",{stretchy:"false"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"t")])]),s("annotation",{encoding:"application/x-tex"},"=\\mathrm{k[{NO}_{2}]^{2}t}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])])])])])])]),s("span",{class:"mord mathrm"},"t")])])])]),a(")")],-1),J=s("p",null,"Given: elementary reactions Asked for: rate law for each elementary reaction and overall rate law",-1),Y=s("h4",{id:"strategy",tabindex:"-1"},[a("Strategy "),s("a",{class:"header-anchor",href:"#strategy","aria-label":'Permalink to "Strategy"'},"​")],-1),K=s("ul",null,[s("li",null,[s("p",null,"Determine the rate law for each elementary reaction in the reaction.")]),s("li",null,[s("p",null,"Determine which rate law corresponds to the experimentally determined rate law for the reaction. This rate law is the one for the rate-determining step.")])],-1),Q=s("h4",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),X=s("details",{class:"details custom-block"},[s("summary",null,"View solution"),s("p",null,[a("A The rate law for step 1 is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"=k_{1}\\left[\\mathrm{NO}_{2}\\right]^{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a("; for step 2 , it is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("msub",null,[s("mi",null,"k"),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"N")]),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")]),s("mo",{fence:"true"},"]")]),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"=k_{2}\\left[\\mathrm{~N}_{2} \\mathrm{O}_{4}\\right][\\mathrm{CO}]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"N")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CO")]),s("span",{class:"mclose"},"]")])])]),a(".")]),s("p",null,[a("B If step 1 is slow (and therefore the rate-determining step), then the overall rate law for the reaction will be the same: rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mn",null,"1")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"k_{1}\\left[\\mathrm{NO}_{2}\\right]^{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.204em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a(". This is the same as the experimentally determined rate law. Hence this mechanism, with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as an intermediate, and the one described previously, with "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as an intermediate, are kinetically indistinguishable. In this case, further experiments are needed to distinguish between them. For example, the researcher could try to detect the proposed intermediates, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{NO}_{3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_{2} \\mathrm{O}_{4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(", directly.")])],-1);function Z(ss,as,ts,ls,es,ns){const t=l;return n(),m("div",null,[c,i(t,{readTime:"11",words:"1.9k"}),p,h,o,g,u,d,v,y,w,x,b,k,f,z,O,_,M,N,C,L,A,B,T,R,I,q,S,P,D,H,E,F,j,U,$,V,W,G,J,Y,K,Q,X])}const ps=e(r,[["render",Z]]);export{cs as __pageData,ps as default}; diff --git a/assets/academic_chemistry_problems_02-20.md.7015a0e8.js b/assets/academic_chemistry_problems_02-20.md.86be96e0.js similarity index 99% rename from assets/academic_chemistry_problems_02-20.md.7015a0e8.js rename to assets/academic_chemistry_problems_02-20.md.86be96e0.js index 28bae3b3..ef3005fa 100644 --- a/assets/academic_chemistry_problems_02-20.md.7015a0e8.js +++ b/assets/academic_chemistry_problems_02-20.md.86be96e0.js @@ -1 +1 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as n,c as e,H as r,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Presentation problem: 02-20","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/02-20.md","filePath":"academic/chemistry/problems/02-20.md","lastUpdated":1695377563000}'),i={name:"academic/chemistry/problems/02-20.md"},p=s("h1",{id:"presentation-problem-02-20",tabindex:"-1"},[a("Presentation problem: 02-20 "),s("a",{class:"header-anchor",href:"#presentation-problem-02-20","aria-label":'Permalink to "Presentation problem: 02-20"'},"​")],-1),c=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),h=s("p",null,[a("At "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"500"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"K")])]),s("annotation",{encoding:"application/x-tex"},"500 \\mathrm{~K}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"500"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"K")])])])]),a(" in the presence of a copper surface, ethanol decomposes according to the equation")],-1),o=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"⟶"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"H")]),s("mn",null,"3")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"H"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}(\\mathrm{g}) \\longrightarrow \\mathrm{CH}_3 \\mathrm{CHO}(g)+\\mathrm{H}_2(g) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⟶"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CH")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CHO")]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),g=s("p",null,[a("The pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" was measured as a function of time and the following data were obtained:")],-1),u=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Time (s)"),s("th",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"P"),s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])])]),s("mtext",null," (torr) ")]),s("annotation",{encoding:"application/x-tex"},"P_{\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}} \\text { (torr) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0001em","vertical-align":"-0.2501em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"OH")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2501em"}},[s("span")])])])])]),s("span",{class:"mord text"},[s("span",{class:"mord"}," (torr) ")])])])])])])]),s("tbody",null,[s("tr",null,[s("td",null,"0"),s("td",null,"250.")]),s("tr",null,[s("td",null,"100."),s("td",null,"237")]),s("tr",null,[s("td",null,"200."),s("td",null,"224")]),s("tr",null,[s("td",null,"300."),s("td",null,"211")]),s("tr",null,[s("td",null,"400."),s("td",null,"198")]),s("tr",null,[s("td",null,"500."),s("td",null,"185")])])],-1),d=s("p",null,[s("strong",null,"Since the pressure of a gas is directly proportional to the concentration of gas"),a(", we can express the rate law for a gaseous reaction in terms of partial pressures. Using the above data, deduce the rate law, the integrated rate law, and the value of the rate constant, all in terms of pressure units in atm and time in seconds. Predict the pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" after "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"900."),s("mi",{mathvariant:"normal"},"s")]),s("annotation",{encoding:"application/x-tex"},"900 . \\mathrm{s}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"900."),s("span",{class:"mord mathrm"},"s")])])]),a(" from the start of the reaction. (Hint: To determine the order of the reaction with respect to "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(", compare how the pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" decreases with each time listing.)")],-1),v=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),y=s("p",null,[s("figure",null,[s("img",{src:"https://r2.toshiki.dev/image/chemistry/solution1.png",alt:"solution graph",title:""}),s("figcaption",{align:"center"},[s("small",null,"◎ ")])])],-1),w=s("p",null,[a("Due to the fact that the graph of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{fence:"true"},"]")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{p}\\left[\\mathrm{O}_2\\right]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),a(" over time is showing "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"R"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{R}^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(" value of 1 we know we have a zero-order reaction. Therefore:")],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"k"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"p"),s("mn",null,"0")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},"]")]),s("mo",null,"−"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},"]")])]),s("mi",{mathvariant:"normal"},"t")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"250"),s("mtext",null," torr "),s("mo",null,"−"),s("mn",null,"185"),s("mtext",null," torr ")]),s("mrow",null,[s("mn",null,"500"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")])])]),s("mo",null,"="),s("mn",null,"0.13"),s("msup",null,[s("mtext",null," torr s "),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"k"),s("mo",null,"="),s("mn",null,"0.13"),s("mtext",null," torr s "),s("msup",null,[s("mi",{mathvariant:"normal"},"s"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"×"),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")])]),s("mrow",null,[s("mn",null,"760"),s("mtext",null," torr ")])]),s("mo",null,"="),s("mn",null,"1.71"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mtext",null," rate "),s("mo",null,"="),s("mi",{mathvariant:"bold"},"k")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"−"),s("mrow",null,[s("mi",{mathvariant:"normal"},"k"),s("mi",{mathvariant:"normal"},"t")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"p"),s("mn",null,"0")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"−"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"1.71"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{fence:"true"},")")]),s("mo",null,"×"),s("mn",null,"900"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",null,"+"),s("mn",null,"0.33"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mn",null,"0.176"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\mathrm{k}=\\frac{\\mathrm{p}_0\\left[\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right]-\\mathrm{p}\\left[\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right]}{\\mathrm{t}}=\\frac{250 \\text { torr }-185 \\text { torr }}{500 \\mathrm{~s}}=0.13 \\text { torr s }^{-1} \\\\ & \\mathrm{k}=0.13 \\text { torr s } \\mathrm{s}^{-1} \\times \\frac{1 \\mathrm{~atm}}{760 \\text { torr }}=1.71 \\times 10^{-4} \\mathrm{~atm} \\mathrm{~s}^{-1} \\\\ & \\text { rate }=\\mathbf{k} \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=-\\mathrm{kt}+\\mathrm{p}_0\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right) \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=-\\left(1.71 \\times 10^{-4} \\mathrm{~atm} \\mathrm{~s}^{-1}\\right) \\times 900 \\mathrm{~s}+0.33 \\mathrm{~atm} \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=0.176 \\mathrm{~atm} \\mathrm{~s}^{-1} \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"12.2687em","vertical-align":"-5.8843em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.3843em"}},[s("span",{style:{top:"-8.3843em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-6.0769em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.2509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.7509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.2268em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"0.2973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"1.7973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8843em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.3843em"}},[s("span",{style:{top:"-8.3843em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"500"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"250"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"185"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.13"),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," torr s ")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"-6.0769em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.13"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr s ")]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"s"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"760"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1.71"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"-4.2509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathbf"},"k")])]),s("span",{style:{top:"-2.7509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"kt")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])]),s("span",{style:{top:"-1.2268em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},"1.71"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"900"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"0.33"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")])])]),s("span",{style:{top:"0.2973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.176"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"1.7973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"})])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8843em"}},[s("span")])])])])])])])])])])],-1);function z(f,x,H,k,_,O){const t=l;return n(),e("div",null,[p,r(t,{readTime:"2",words:"412"}),c,h,o,g,u,d,v,y,w,b])}const T=m(i,[["render",z]]);export{L as __pageData,T as default}; +import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as n,c as e,H as r,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Presentation problem: 02-20","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/02-20.md","filePath":"academic/chemistry/problems/02-20.md","lastUpdated":1699051935000}'),i={name:"academic/chemistry/problems/02-20.md"},p=s("h1",{id:"presentation-problem-02-20",tabindex:"-1"},[a("Presentation problem: 02-20 "),s("a",{class:"header-anchor",href:"#presentation-problem-02-20","aria-label":'Permalink to "Presentation problem: 02-20"'},"​")],-1),c=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),h=s("p",null,[a("At "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"500"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"K")])]),s("annotation",{encoding:"application/x-tex"},"500 \\mathrm{~K}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"500"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"K")])])])]),a(" in the presence of a copper surface, ethanol decomposes according to the equation")],-1),o=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"⟶"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"H")]),s("mn",null,"3")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"H"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}(\\mathrm{g}) \\longrightarrow \\mathrm{CH}_3 \\mathrm{CHO}(g)+\\mathrm{H}_2(g) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⟶"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CH")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CHO")]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),g=s("p",null,[a("The pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" was measured as a function of time and the following data were obtained:")],-1),u=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Time (s)"),s("th",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"P"),s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])])]),s("mtext",null," (torr) ")]),s("annotation",{encoding:"application/x-tex"},"P_{\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}} \\text { (torr) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0001em","vertical-align":"-0.2501em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"OH")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2501em"}},[s("span")])])])])]),s("span",{class:"mord text"},[s("span",{class:"mord"}," (torr) ")])])])])])])]),s("tbody",null,[s("tr",null,[s("td",null,"0"),s("td",null,"250.")]),s("tr",null,[s("td",null,"100."),s("td",null,"237")]),s("tr",null,[s("td",null,"200."),s("td",null,"224")]),s("tr",null,[s("td",null,"300."),s("td",null,"211")]),s("tr",null,[s("td",null,"400."),s("td",null,"198")]),s("tr",null,[s("td",null,"500."),s("td",null,"185")])])],-1),d=s("p",null,[s("strong",null,"Since the pressure of a gas is directly proportional to the concentration of gas"),a(", we can express the rate law for a gaseous reaction in terms of partial pressures. Using the above data, deduce the rate law, the integrated rate law, and the value of the rate constant, all in terms of pressure units in atm and time in seconds. Predict the pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" after "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"900."),s("mi",{mathvariant:"normal"},"s")]),s("annotation",{encoding:"application/x-tex"},"900 . \\mathrm{s}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"900."),s("span",{class:"mord mathrm"},"s")])])]),a(" from the start of the reaction. (Hint: To determine the order of the reaction with respect to "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(", compare how the pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" decreases with each time listing.)")],-1),v=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),y=s("p",null,[s("figure",null,[s("img",{src:"https://r2.toshiki.dev/image/chemistry/solution1.png",alt:"solution graph",title:""}),s("figcaption",{align:"center"},[s("small",null,"◎ ")])])],-1),w=s("p",null,[a("Due to the fact that the graph of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{fence:"true"},"]")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{p}\\left[\\mathrm{O}_2\\right]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),a(" over time is showing "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"R"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{R}^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(" value of 1 we know we have a zero-order reaction. Therefore:")],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"k"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"p"),s("mn",null,"0")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},"]")]),s("mo",null,"−"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},"]")])]),s("mi",{mathvariant:"normal"},"t")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"250"),s("mtext",null," torr "),s("mo",null,"−"),s("mn",null,"185"),s("mtext",null," torr ")]),s("mrow",null,[s("mn",null,"500"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")])])]),s("mo",null,"="),s("mn",null,"0.13"),s("msup",null,[s("mtext",null," torr s "),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"k"),s("mo",null,"="),s("mn",null,"0.13"),s("mtext",null," torr s "),s("msup",null,[s("mi",{mathvariant:"normal"},"s"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"×"),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")])]),s("mrow",null,[s("mn",null,"760"),s("mtext",null," torr ")])]),s("mo",null,"="),s("mn",null,"1.71"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mtext",null," rate "),s("mo",null,"="),s("mi",{mathvariant:"bold"},"k")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"−"),s("mrow",null,[s("mi",{mathvariant:"normal"},"k"),s("mi",{mathvariant:"normal"},"t")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"p"),s("mn",null,"0")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"−"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"1.71"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{fence:"true"},")")]),s("mo",null,"×"),s("mn",null,"900"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",null,"+"),s("mn",null,"0.33"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mn",null,"0.176"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\mathrm{k}=\\frac{\\mathrm{p}_0\\left[\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right]-\\mathrm{p}\\left[\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right]}{\\mathrm{t}}=\\frac{250 \\text { torr }-185 \\text { torr }}{500 \\mathrm{~s}}=0.13 \\text { torr s }^{-1} \\\\ & \\mathrm{k}=0.13 \\text { torr s } \\mathrm{s}^{-1} \\times \\frac{1 \\mathrm{~atm}}{760 \\text { torr }}=1.71 \\times 10^{-4} \\mathrm{~atm} \\mathrm{~s}^{-1} \\\\ & \\text { rate }=\\mathbf{k} \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=-\\mathrm{kt}+\\mathrm{p}_0\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right) \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=-\\left(1.71 \\times 10^{-4} \\mathrm{~atm} \\mathrm{~s}^{-1}\\right) \\times 900 \\mathrm{~s}+0.33 \\mathrm{~atm} \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=0.176 \\mathrm{~atm} \\mathrm{~s}^{-1} \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"12.2687em","vertical-align":"-5.8843em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.3843em"}},[s("span",{style:{top:"-8.3843em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-6.0769em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.2509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.7509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.2268em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"0.2973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"1.7973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8843em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.3843em"}},[s("span",{style:{top:"-8.3843em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"500"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"250"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"185"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.13"),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," torr s ")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"-6.0769em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.13"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr s ")]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"s"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"760"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1.71"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"-4.2509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathbf"},"k")])]),s("span",{style:{top:"-2.7509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"kt")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])]),s("span",{style:{top:"-1.2268em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},"1.71"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"900"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"0.33"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")])])]),s("span",{style:{top:"0.2973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.176"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"1.7973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"})])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8843em"}},[s("span")])])])])])])])])])])],-1);function z(f,x,H,k,_,O){const t=l;return n(),e("div",null,[p,r(t,{readTime:"2",words:"412"}),c,h,o,g,u,d,v,y,w,b])}const T=m(i,[["render",z]]);export{L as __pageData,T as default}; diff --git a/assets/academic_chemistry_problems_02-20.md.7015a0e8.lean.js b/assets/academic_chemistry_problems_02-20.md.86be96e0.lean.js similarity index 99% rename from assets/academic_chemistry_problems_02-20.md.7015a0e8.lean.js rename to assets/academic_chemistry_problems_02-20.md.86be96e0.lean.js index 28bae3b3..ef3005fa 100644 --- a/assets/academic_chemistry_problems_02-20.md.7015a0e8.lean.js +++ b/assets/academic_chemistry_problems_02-20.md.86be96e0.lean.js @@ -1 +1 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as n,c as e,H as r,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Presentation problem: 02-20","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/02-20.md","filePath":"academic/chemistry/problems/02-20.md","lastUpdated":1695377563000}'),i={name:"academic/chemistry/problems/02-20.md"},p=s("h1",{id:"presentation-problem-02-20",tabindex:"-1"},[a("Presentation problem: 02-20 "),s("a",{class:"header-anchor",href:"#presentation-problem-02-20","aria-label":'Permalink to "Presentation problem: 02-20"'},"​")],-1),c=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),h=s("p",null,[a("At "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"500"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"K")])]),s("annotation",{encoding:"application/x-tex"},"500 \\mathrm{~K}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"500"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"K")])])])]),a(" in the presence of a copper surface, ethanol decomposes according to the equation")],-1),o=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"⟶"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"H")]),s("mn",null,"3")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"H"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}(\\mathrm{g}) \\longrightarrow \\mathrm{CH}_3 \\mathrm{CHO}(g)+\\mathrm{H}_2(g) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⟶"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CH")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CHO")]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),g=s("p",null,[a("The pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" was measured as a function of time and the following data were obtained:")],-1),u=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Time (s)"),s("th",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"P"),s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])])]),s("mtext",null," (torr) ")]),s("annotation",{encoding:"application/x-tex"},"P_{\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}} \\text { (torr) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0001em","vertical-align":"-0.2501em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"OH")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2501em"}},[s("span")])])])])]),s("span",{class:"mord text"},[s("span",{class:"mord"}," (torr) ")])])])])])])]),s("tbody",null,[s("tr",null,[s("td",null,"0"),s("td",null,"250.")]),s("tr",null,[s("td",null,"100."),s("td",null,"237")]),s("tr",null,[s("td",null,"200."),s("td",null,"224")]),s("tr",null,[s("td",null,"300."),s("td",null,"211")]),s("tr",null,[s("td",null,"400."),s("td",null,"198")]),s("tr",null,[s("td",null,"500."),s("td",null,"185")])])],-1),d=s("p",null,[s("strong",null,"Since the pressure of a gas is directly proportional to the concentration of gas"),a(", we can express the rate law for a gaseous reaction in terms of partial pressures. Using the above data, deduce the rate law, the integrated rate law, and the value of the rate constant, all in terms of pressure units in atm and time in seconds. Predict the pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" after "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"900."),s("mi",{mathvariant:"normal"},"s")]),s("annotation",{encoding:"application/x-tex"},"900 . \\mathrm{s}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"900."),s("span",{class:"mord mathrm"},"s")])])]),a(" from the start of the reaction. (Hint: To determine the order of the reaction with respect to "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(", compare how the pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" decreases with each time listing.)")],-1),v=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),y=s("p",null,[s("figure",null,[s("img",{src:"https://r2.toshiki.dev/image/chemistry/solution1.png",alt:"solution graph",title:""}),s("figcaption",{align:"center"},[s("small",null,"◎ ")])])],-1),w=s("p",null,[a("Due to the fact that the graph of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{fence:"true"},"]")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{p}\\left[\\mathrm{O}_2\\right]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),a(" over time is showing "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"R"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{R}^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(" value of 1 we know we have a zero-order reaction. Therefore:")],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"k"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"p"),s("mn",null,"0")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},"]")]),s("mo",null,"−"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},"]")])]),s("mi",{mathvariant:"normal"},"t")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"250"),s("mtext",null," torr "),s("mo",null,"−"),s("mn",null,"185"),s("mtext",null," torr ")]),s("mrow",null,[s("mn",null,"500"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")])])]),s("mo",null,"="),s("mn",null,"0.13"),s("msup",null,[s("mtext",null," torr s "),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"k"),s("mo",null,"="),s("mn",null,"0.13"),s("mtext",null," torr s "),s("msup",null,[s("mi",{mathvariant:"normal"},"s"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"×"),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")])]),s("mrow",null,[s("mn",null,"760"),s("mtext",null," torr ")])]),s("mo",null,"="),s("mn",null,"1.71"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mtext",null," rate "),s("mo",null,"="),s("mi",{mathvariant:"bold"},"k")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"−"),s("mrow",null,[s("mi",{mathvariant:"normal"},"k"),s("mi",{mathvariant:"normal"},"t")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"p"),s("mn",null,"0")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"−"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"1.71"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{fence:"true"},")")]),s("mo",null,"×"),s("mn",null,"900"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",null,"+"),s("mn",null,"0.33"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mn",null,"0.176"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\mathrm{k}=\\frac{\\mathrm{p}_0\\left[\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right]-\\mathrm{p}\\left[\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right]}{\\mathrm{t}}=\\frac{250 \\text { torr }-185 \\text { torr }}{500 \\mathrm{~s}}=0.13 \\text { torr s }^{-1} \\\\ & \\mathrm{k}=0.13 \\text { torr s } \\mathrm{s}^{-1} \\times \\frac{1 \\mathrm{~atm}}{760 \\text { torr }}=1.71 \\times 10^{-4} \\mathrm{~atm} \\mathrm{~s}^{-1} \\\\ & \\text { rate }=\\mathbf{k} \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=-\\mathrm{kt}+\\mathrm{p}_0\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right) \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=-\\left(1.71 \\times 10^{-4} \\mathrm{~atm} \\mathrm{~s}^{-1}\\right) \\times 900 \\mathrm{~s}+0.33 \\mathrm{~atm} \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=0.176 \\mathrm{~atm} \\mathrm{~s}^{-1} \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"12.2687em","vertical-align":"-5.8843em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.3843em"}},[s("span",{style:{top:"-8.3843em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-6.0769em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.2509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.7509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.2268em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"0.2973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"1.7973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8843em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.3843em"}},[s("span",{style:{top:"-8.3843em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"500"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"250"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"185"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.13"),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," torr s ")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"-6.0769em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.13"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr s ")]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"s"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"760"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1.71"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"-4.2509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathbf"},"k")])]),s("span",{style:{top:"-2.7509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"kt")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])]),s("span",{style:{top:"-1.2268em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},"1.71"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"900"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"0.33"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")])])]),s("span",{style:{top:"0.2973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.176"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"1.7973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"})])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8843em"}},[s("span")])])])])])])])])])])],-1);function z(f,x,H,k,_,O){const t=l;return n(),e("div",null,[p,r(t,{readTime:"2",words:"412"}),c,h,o,g,u,d,v,y,w,b])}const T=m(i,[["render",z]]);export{L as __pageData,T as default}; +import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as n,c as e,H as r,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Presentation problem: 02-20","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/02-20.md","filePath":"academic/chemistry/problems/02-20.md","lastUpdated":1699051935000}'),i={name:"academic/chemistry/problems/02-20.md"},p=s("h1",{id:"presentation-problem-02-20",tabindex:"-1"},[a("Presentation problem: 02-20 "),s("a",{class:"header-anchor",href:"#presentation-problem-02-20","aria-label":'Permalink to "Presentation problem: 02-20"'},"​")],-1),c=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),h=s("p",null,[a("At "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"500"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"K")])]),s("annotation",{encoding:"application/x-tex"},"500 \\mathrm{~K}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"500"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"K")])])])]),a(" in the presence of a copper surface, ethanol decomposes according to the equation")],-1),o=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"⟶"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"H")]),s("mn",null,"3")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"C"),s("mi",{mathvariant:"normal"},"H"),s("mi",{mathvariant:"normal"},"O")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}(\\mathrm{g}) \\longrightarrow \\mathrm{CH}_3 \\mathrm{CHO}(g)+\\mathrm{H}_2(g) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⟶"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CH")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"CHO")]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),g=s("p",null,[a("The pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" was measured as a function of time and the following data were obtained:")],-1),u=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Time (s)"),s("th",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"P"),s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])])]),s("mtext",null," (torr) ")]),s("annotation",{encoding:"application/x-tex"},"P_{\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}} \\text { (torr) }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0001em","vertical-align":"-0.2501em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"OH")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2501em"}},[s("span")])])])])]),s("span",{class:"mord text"},[s("span",{class:"mord"}," (torr) ")])])])])])])]),s("tbody",null,[s("tr",null,[s("td",null,"0"),s("td",null,"250.")]),s("tr",null,[s("td",null,"100."),s("td",null,"237")]),s("tr",null,[s("td",null,"200."),s("td",null,"224")]),s("tr",null,[s("td",null,"300."),s("td",null,"211")]),s("tr",null,[s("td",null,"400."),s("td",null,"198")]),s("tr",null,[s("td",null,"500."),s("td",null,"185")])])],-1),d=s("p",null,[s("strong",null,"Since the pressure of a gas is directly proportional to the concentration of gas"),a(", we can express the rate law for a gaseous reaction in terms of partial pressures. Using the above data, deduce the rate law, the integrated rate law, and the value of the rate constant, all in terms of pressure units in atm and time in seconds. Predict the pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" after "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"900."),s("mi",{mathvariant:"normal"},"s")]),s("annotation",{encoding:"application/x-tex"},"900 . \\mathrm{s}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"900."),s("span",{class:"mord mathrm"},"s")])])]),a(" from the start of the reaction. (Hint: To determine the order of the reaction with respect to "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(", compare how the pressure of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")])])])]),a(" decreases with each time listing.)")],-1),v=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),y=s("p",null,[s("figure",null,[s("img",{src:"https://r2.toshiki.dev/image/chemistry/solution1.png",alt:"solution graph",title:""}),s("figcaption",{align:"center"},[s("small",null,"◎ ")])])],-1),w=s("p",null,[a("Due to the fact that the graph of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{fence:"true"},"]")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{p}\\left[\\mathrm{O}_2\\right]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),a(" over time is showing "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"R"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{R}^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(" value of 1 we know we have a zero-order reaction. Therefore:")],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"k"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"p"),s("mn",null,"0")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},"]")]),s("mo",null,"−"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},"]")])]),s("mi",{mathvariant:"normal"},"t")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"250"),s("mtext",null," torr "),s("mo",null,"−"),s("mn",null,"185"),s("mtext",null," torr ")]),s("mrow",null,[s("mn",null,"500"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")])])]),s("mo",null,"="),s("mn",null,"0.13"),s("msup",null,[s("mtext",null," torr s "),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"k"),s("mo",null,"="),s("mn",null,"0.13"),s("mtext",null," torr s "),s("msup",null,[s("mi",{mathvariant:"normal"},"s"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"×"),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")])]),s("mrow",null,[s("mn",null,"760"),s("mtext",null," torr ")])]),s("mo",null,"="),s("mn",null,"1.71"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mtext",null," rate "),s("mo",null,"="),s("mi",{mathvariant:"bold"},"k")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"−"),s("mrow",null,[s("mi",{mathvariant:"normal"},"k"),s("mi",{mathvariant:"normal"},"t")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"p"),s("mn",null,"0")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"−"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"1.71"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{fence:"true"},")")]),s("mo",null,"×"),s("mn",null,"900"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",null,"+"),s("mn",null,"0.33"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"normal"},"p"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"normal"},"C"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"H"),s("mn",null,"5")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"O"),s("mi",{mathvariant:"normal"},"H")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mn",null,"0.176"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"a"),s("mi",{mathvariant:"normal"},"t"),s("mi",{mathvariant:"normal"},"m")]),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\mathrm{k}=\\frac{\\mathrm{p}_0\\left[\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right]-\\mathrm{p}\\left[\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right]}{\\mathrm{t}}=\\frac{250 \\text { torr }-185 \\text { torr }}{500 \\mathrm{~s}}=0.13 \\text { torr s }^{-1} \\\\ & \\mathrm{k}=0.13 \\text { torr s } \\mathrm{s}^{-1} \\times \\frac{1 \\mathrm{~atm}}{760 \\text { torr }}=1.71 \\times 10^{-4} \\mathrm{~atm} \\mathrm{~s}^{-1} \\\\ & \\text { rate }=\\mathbf{k} \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=-\\mathrm{kt}+\\mathrm{p}_0\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right) \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=-\\left(1.71 \\times 10^{-4} \\mathrm{~atm} \\mathrm{~s}^{-1}\\right) \\times 900 \\mathrm{~s}+0.33 \\mathrm{~atm} \\\\ & \\mathrm{p}\\left(\\mathrm{C}_2 \\mathrm{H}_5 \\mathrm{OH}\\right)=0.176 \\mathrm{~atm} \\mathrm{~s}^{-1} \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"12.2687em","vertical-align":"-5.8843em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.3843em"}},[s("span",{style:{top:"-8.3843em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-6.0769em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.2509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.7509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.2268em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"0.2973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"1.7973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8843em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.3843em"}},[s("span",{style:{top:"-8.3843em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"500"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"250"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"185"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.13"),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," torr s ")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"-6.0769em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.13"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr s ")]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"s"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"760"),s("span",{class:"mord text"},[s("span",{class:"mord"}," torr ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1.71"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"-4.2509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathbf"},"k")])]),s("span",{style:{top:"-2.7509em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"kt")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])]),s("span",{style:{top:"-1.2268em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},"1.71"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"900"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"0.33"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")])])]),s("span",{style:{top:"0.2973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathrm"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"C"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"H"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"OH")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.176"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"atm")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])]),s("span",{style:{top:"1.7973em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"})])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8843em"}},[s("span")])])])])])])])])])])],-1);function z(f,x,H,k,_,O){const t=l;return n(),e("div",null,[p,r(t,{readTime:"2",words:"412"}),c,h,o,g,u,d,v,y,w,b])}const T=m(i,[["render",z]]);export{L as __pageData,T as default}; diff --git a/assets/academic_chemistry_problems_03-02-1.md.054898d2.js b/assets/academic_chemistry_problems_03-02-1.md.a9ee56be.js similarity index 99% rename from assets/academic_chemistry_problems_03-02-1.md.054898d2.js rename to assets/academic_chemistry_problems_03-02-1.md.a9ee56be.js index c57d41f3..9feb3a1f 100644 --- a/assets/academic_chemistry_problems_03-02-1.md.054898d2.js +++ b/assets/academic_chemistry_problems_03-02-1.md.a9ee56be.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as m,H as c,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const q=JSON.parse('{"title":"Problem: 03-02-1","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-1.md","filePath":"academic/chemistry/problems/03-02-1.md","lastUpdated":1695377563000}'),i={name:"academic/chemistry/problems/03-02-1.md"},p=s("h1",{id:"problem-03-02-1",tabindex:"-1"},[a("Problem: 03-02-1 "),s("a",{class:"header-anchor",href:"#problem-03-02-1","aria-label":'Permalink to "Problem: 03-02-1"'},"​")],-1),r=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),o=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"N")]),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"→"),s("mn",null,"4"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{~N}_2 \\mathrm{O}_5(g) \\rightarrow 4 \\mathrm{NO}_2(g)+\\mathrm{O}_2(g) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"N")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),h=s("p",null,[a("The decomposition of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5(g)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])]),a(" is represented by the equation above. A sample of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5(g)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])]),a(" is monitored as it decomposes, and the concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as a function of time is recorded. The results are shown in the table below.")],-1),g=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Time (s)"),s("th",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{[N_2O_5]}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose"},"]")])])])])])])]),s("tbody",null,[s("tr",null,[s("td",null,"0"),s("td",null,"1.000")]),s("tr",null,[s("td",null,"25.0"),s("td",null,"0.801")]),s("tr",null,[s("td",null,"50.0"),s("td",null,"0.642")]),s("tr",null,[s("td",null,"75.0"),s("td",null,"0.515")])])],-1),u=s("p",null,[a("Calculate the average rate of the reaction between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds.")],-1),y=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),d=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"+"),s("mi",null,"b"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"B")]),s("mo",null,"→"),s("mi",null,"c"),s("mi",{mathvariant:"normal"},"C"),s("mo",null,"+"),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"D")]),s("annotation",{encoding:"application/x-tex"},"a \\mathrm{~A}+b \\mathrm{~B} \\rightarrow c \\mathrm{C}+d \\mathrm{D} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"B")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord mathrm"},"D")])])])])],-1),v=s("p",null,"the rate of reaction is defined as",-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mstyle",{mathcolor:"cyan"},[s("mtext",null," rate "),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"a")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"A"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"b")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"c")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"C"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"d")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"D"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])])])]),s("annotation",{encoding:"application/x-tex"},"\\color{cyan}\\text { rate }=-\\frac{1}{a} \\frac{\\Delta[\\mathrm{A}]}{\\Delta t}=-\\frac{1}{b} \\frac{\\Delta[\\mathrm{B}]}{\\Delta t}=+\\frac{1}{c} \\frac{\\Delta[\\mathrm{C}]}{\\Delta t}=+\\frac{1}{d} \\frac{\\Delta[\\mathrm{D}]}{\\Delta t} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"−"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"a")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"A"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"−"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"b")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"B"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"+"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"c")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"C"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"+"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"D"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),x=s("p",null,[a("Notice that the rate of change in concentration of each species is divided by its coefficient from the balanced chemical equation ( "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(", "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"b"),s("mo",{separator:"true"},","),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"b, c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(", or "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" ). This ensures that the calculated reaction rate is the same no matter which reactant or product is monitored for changes in concentration. In this case, the monitored species was "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". With that in mind, let's write the reaction rate in terms of the rate of change in concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" :")],-1),w=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{fence:"true"},"]")])]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=-\\frac{1}{2} \\frac{\\Delta\\left[\\mathrm{N}_2 \\mathrm{O}_5\\right]}{\\Delta t} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"Δ"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),f=s("p",null,[a("Since the coefficient for "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" in the balanced equation is 2 , we divided the rate of change in concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" by 2 . Additionally, since "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" is being consumed in the reaction, we included a negative sign in front of the expression.")],-1),k=s("p",null,[a("Now, let's plug in the information from the table to calculate the average reaction rate between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds:")],-1),z=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mtext",null," rate ")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mfrac",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"0.515"),s("mi",null,"M"),s("mo",null,"−"),s("mn",null,"0.642"),s("mi",null,"M"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"75.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",null,"−"),s("mn",null,"50.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",{stretchy:"false"},")")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mn",null,"2.54"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"3")])]),s("mi",null,"M"),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} \\text { rate } & =-\\frac{1}{2} \\frac{(0.515 M-0.642 M)}{(75.0 \\mathrm{~s}-50.0 \\mathrm{~s})} \\\\ & =2.54 \\times 10^{-3} M \\mathrm{~s}^{-1} \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"4.1871em","vertical-align":"-1.8436em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3436em"}},[s("span",{style:{top:"-4.3436em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")])])]),s("span",{style:{top:"-2.2434em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.8436em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3436em"}},[s("span",{style:{top:"-4.3436em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"75.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"50.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"0.515"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"0.642"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-2.2434em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2.54"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"3")])])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.8436em"}},[s("span")])])])])])])])])])])],-1),M=s("p",null,[a("So, the average rate of the reaction between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",{mathvariant:"bold"},"2.54"),s("mo",null,"×"),s("mn",{mathvariant:"bold"},"1"),s("msup",null,[s("mn",{mathvariant:"bold"},"0"),s("mrow",null,[s("mo",null,"−"),s("mn",{mathvariant:"bold"},"3")])]),s("mi",{mathvariant:"normal"},"M"),s("msup",null,[s("mi",{mathvariant:"normal"},"s"),s("mrow",null,[s("mo",null,"−"),s("mn",{mathvariant:"bold"},"1")])])]),s("annotation",{encoding:"application/x-tex"},"\\bold{2.54 \\times 10^{-3} \\mathrm{M} \\mathrm{s}^{-1}}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8974em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathbf"},"2.54"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathbf"},"1"),s("span",{class:"mord"},[s("span",{class:"mord mathbf"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathbf mtight"},"3")])])])])])])])]),s("span",{class:"mord mathrm"},"M"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"s"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathbf mtight"},"1")])])])])])])])])])])])]),a(".")],-1);function _(N,O,L,D,B,P){const l=t;return e(),m("div",null,[p,c(l,{readTime:"2",words:"404"}),r,o,h,g,u,y,d,v,b,x,w,f,k,z,M])}const S=n(i,[["render",_]]);export{q as __pageData,S as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as m,H as c,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const q=JSON.parse('{"title":"Problem: 03-02-1","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-1.md","filePath":"academic/chemistry/problems/03-02-1.md","lastUpdated":1699051935000}'),i={name:"academic/chemistry/problems/03-02-1.md"},p=s("h1",{id:"problem-03-02-1",tabindex:"-1"},[a("Problem: 03-02-1 "),s("a",{class:"header-anchor",href:"#problem-03-02-1","aria-label":'Permalink to "Problem: 03-02-1"'},"​")],-1),r=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),o=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"N")]),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"→"),s("mn",null,"4"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{~N}_2 \\mathrm{O}_5(g) \\rightarrow 4 \\mathrm{NO}_2(g)+\\mathrm{O}_2(g) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"N")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),h=s("p",null,[a("The decomposition of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5(g)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])]),a(" is represented by the equation above. A sample of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5(g)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])]),a(" is monitored as it decomposes, and the concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as a function of time is recorded. The results are shown in the table below.")],-1),g=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Time (s)"),s("th",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{[N_2O_5]}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose"},"]")])])])])])])]),s("tbody",null,[s("tr",null,[s("td",null,"0"),s("td",null,"1.000")]),s("tr",null,[s("td",null,"25.0"),s("td",null,"0.801")]),s("tr",null,[s("td",null,"50.0"),s("td",null,"0.642")]),s("tr",null,[s("td",null,"75.0"),s("td",null,"0.515")])])],-1),u=s("p",null,[a("Calculate the average rate of the reaction between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds.")],-1),y=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),d=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"+"),s("mi",null,"b"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"B")]),s("mo",null,"→"),s("mi",null,"c"),s("mi",{mathvariant:"normal"},"C"),s("mo",null,"+"),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"D")]),s("annotation",{encoding:"application/x-tex"},"a \\mathrm{~A}+b \\mathrm{~B} \\rightarrow c \\mathrm{C}+d \\mathrm{D} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"B")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord mathrm"},"D")])])])])],-1),v=s("p",null,"the rate of reaction is defined as",-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mstyle",{mathcolor:"cyan"},[s("mtext",null," rate "),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"a")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"A"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"b")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"c")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"C"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"d")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"D"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])])])]),s("annotation",{encoding:"application/x-tex"},"\\color{cyan}\\text { rate }=-\\frac{1}{a} \\frac{\\Delta[\\mathrm{A}]}{\\Delta t}=-\\frac{1}{b} \\frac{\\Delta[\\mathrm{B}]}{\\Delta t}=+\\frac{1}{c} \\frac{\\Delta[\\mathrm{C}]}{\\Delta t}=+\\frac{1}{d} \\frac{\\Delta[\\mathrm{D}]}{\\Delta t} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"−"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"a")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"A"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"−"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"b")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"B"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"+"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"c")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"C"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"+"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"D"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),x=s("p",null,[a("Notice that the rate of change in concentration of each species is divided by its coefficient from the balanced chemical equation ( "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(", "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"b"),s("mo",{separator:"true"},","),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"b, c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(", or "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" ). This ensures that the calculated reaction rate is the same no matter which reactant or product is monitored for changes in concentration. In this case, the monitored species was "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". With that in mind, let's write the reaction rate in terms of the rate of change in concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" :")],-1),w=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{fence:"true"},"]")])]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=-\\frac{1}{2} \\frac{\\Delta\\left[\\mathrm{N}_2 \\mathrm{O}_5\\right]}{\\Delta t} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"Δ"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),f=s("p",null,[a("Since the coefficient for "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" in the balanced equation is 2 , we divided the rate of change in concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" by 2 . Additionally, since "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" is being consumed in the reaction, we included a negative sign in front of the expression.")],-1),k=s("p",null,[a("Now, let's plug in the information from the table to calculate the average reaction rate between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds:")],-1),z=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mtext",null," rate ")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mfrac",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"0.515"),s("mi",null,"M"),s("mo",null,"−"),s("mn",null,"0.642"),s("mi",null,"M"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"75.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",null,"−"),s("mn",null,"50.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",{stretchy:"false"},")")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mn",null,"2.54"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"3")])]),s("mi",null,"M"),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} \\text { rate } & =-\\frac{1}{2} \\frac{(0.515 M-0.642 M)}{(75.0 \\mathrm{~s}-50.0 \\mathrm{~s})} \\\\ & =2.54 \\times 10^{-3} M \\mathrm{~s}^{-1} \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"4.1871em","vertical-align":"-1.8436em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3436em"}},[s("span",{style:{top:"-4.3436em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")])])]),s("span",{style:{top:"-2.2434em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.8436em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3436em"}},[s("span",{style:{top:"-4.3436em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"75.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"50.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"0.515"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"0.642"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-2.2434em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2.54"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"3")])])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.8436em"}},[s("span")])])])])])])])])])])],-1),M=s("p",null,[a("So, the average rate of the reaction between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",{mathvariant:"bold"},"2.54"),s("mo",null,"×"),s("mn",{mathvariant:"bold"},"1"),s("msup",null,[s("mn",{mathvariant:"bold"},"0"),s("mrow",null,[s("mo",null,"−"),s("mn",{mathvariant:"bold"},"3")])]),s("mi",{mathvariant:"normal"},"M"),s("msup",null,[s("mi",{mathvariant:"normal"},"s"),s("mrow",null,[s("mo",null,"−"),s("mn",{mathvariant:"bold"},"1")])])]),s("annotation",{encoding:"application/x-tex"},"\\bold{2.54 \\times 10^{-3} \\mathrm{M} \\mathrm{s}^{-1}}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8974em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathbf"},"2.54"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathbf"},"1"),s("span",{class:"mord"},[s("span",{class:"mord mathbf"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathbf mtight"},"3")])])])])])])])]),s("span",{class:"mord mathrm"},"M"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"s"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathbf mtight"},"1")])])])])])])])])])])])]),a(".")],-1);function _(N,O,L,D,B,P){const l=t;return e(),m("div",null,[p,c(l,{readTime:"2",words:"404"}),r,o,h,g,u,y,d,v,b,x,w,f,k,z,M])}const S=n(i,[["render",_]]);export{q as __pageData,S as default}; diff --git a/assets/academic_chemistry_problems_03-02-1.md.054898d2.lean.js b/assets/academic_chemistry_problems_03-02-1.md.a9ee56be.lean.js similarity index 99% rename from assets/academic_chemistry_problems_03-02-1.md.054898d2.lean.js rename to assets/academic_chemistry_problems_03-02-1.md.a9ee56be.lean.js index c57d41f3..9feb3a1f 100644 --- a/assets/academic_chemistry_problems_03-02-1.md.054898d2.lean.js +++ b/assets/academic_chemistry_problems_03-02-1.md.a9ee56be.lean.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as m,H as c,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const q=JSON.parse('{"title":"Problem: 03-02-1","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-1.md","filePath":"academic/chemistry/problems/03-02-1.md","lastUpdated":1695377563000}'),i={name:"academic/chemistry/problems/03-02-1.md"},p=s("h1",{id:"problem-03-02-1",tabindex:"-1"},[a("Problem: 03-02-1 "),s("a",{class:"header-anchor",href:"#problem-03-02-1","aria-label":'Permalink to "Problem: 03-02-1"'},"​")],-1),r=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),o=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"N")]),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"→"),s("mn",null,"4"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{~N}_2 \\mathrm{O}_5(g) \\rightarrow 4 \\mathrm{NO}_2(g)+\\mathrm{O}_2(g) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"N")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),h=s("p",null,[a("The decomposition of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5(g)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])]),a(" is represented by the equation above. A sample of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5(g)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])]),a(" is monitored as it decomposes, and the concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as a function of time is recorded. The results are shown in the table below.")],-1),g=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Time (s)"),s("th",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{[N_2O_5]}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose"},"]")])])])])])])]),s("tbody",null,[s("tr",null,[s("td",null,"0"),s("td",null,"1.000")]),s("tr",null,[s("td",null,"25.0"),s("td",null,"0.801")]),s("tr",null,[s("td",null,"50.0"),s("td",null,"0.642")]),s("tr",null,[s("td",null,"75.0"),s("td",null,"0.515")])])],-1),u=s("p",null,[a("Calculate the average rate of the reaction between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds.")],-1),y=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),d=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"+"),s("mi",null,"b"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"B")]),s("mo",null,"→"),s("mi",null,"c"),s("mi",{mathvariant:"normal"},"C"),s("mo",null,"+"),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"D")]),s("annotation",{encoding:"application/x-tex"},"a \\mathrm{~A}+b \\mathrm{~B} \\rightarrow c \\mathrm{C}+d \\mathrm{D} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"B")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord mathrm"},"D")])])])])],-1),v=s("p",null,"the rate of reaction is defined as",-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mstyle",{mathcolor:"cyan"},[s("mtext",null," rate "),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"a")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"A"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"b")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"c")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"C"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"d")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"D"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])])])]),s("annotation",{encoding:"application/x-tex"},"\\color{cyan}\\text { rate }=-\\frac{1}{a} \\frac{\\Delta[\\mathrm{A}]}{\\Delta t}=-\\frac{1}{b} \\frac{\\Delta[\\mathrm{B}]}{\\Delta t}=+\\frac{1}{c} \\frac{\\Delta[\\mathrm{C}]}{\\Delta t}=+\\frac{1}{d} \\frac{\\Delta[\\mathrm{D}]}{\\Delta t} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"−"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"a")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"A"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"−"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"b")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"B"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"+"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"c")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"C"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"+"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"D"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),x=s("p",null,[a("Notice that the rate of change in concentration of each species is divided by its coefficient from the balanced chemical equation ( "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(", "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"b"),s("mo",{separator:"true"},","),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"b, c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(", or "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" ). This ensures that the calculated reaction rate is the same no matter which reactant or product is monitored for changes in concentration. In this case, the monitored species was "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". With that in mind, let's write the reaction rate in terms of the rate of change in concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" :")],-1),w=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{fence:"true"},"]")])]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=-\\frac{1}{2} \\frac{\\Delta\\left[\\mathrm{N}_2 \\mathrm{O}_5\\right]}{\\Delta t} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"Δ"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),f=s("p",null,[a("Since the coefficient for "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" in the balanced equation is 2 , we divided the rate of change in concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" by 2 . Additionally, since "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" is being consumed in the reaction, we included a negative sign in front of the expression.")],-1),k=s("p",null,[a("Now, let's plug in the information from the table to calculate the average reaction rate between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds:")],-1),z=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mtext",null," rate ")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mfrac",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"0.515"),s("mi",null,"M"),s("mo",null,"−"),s("mn",null,"0.642"),s("mi",null,"M"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"75.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",null,"−"),s("mn",null,"50.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",{stretchy:"false"},")")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mn",null,"2.54"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"3")])]),s("mi",null,"M"),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} \\text { rate } & =-\\frac{1}{2} \\frac{(0.515 M-0.642 M)}{(75.0 \\mathrm{~s}-50.0 \\mathrm{~s})} \\\\ & =2.54 \\times 10^{-3} M \\mathrm{~s}^{-1} \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"4.1871em","vertical-align":"-1.8436em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3436em"}},[s("span",{style:{top:"-4.3436em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")])])]),s("span",{style:{top:"-2.2434em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.8436em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3436em"}},[s("span",{style:{top:"-4.3436em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"75.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"50.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"0.515"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"0.642"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-2.2434em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2.54"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"3")])])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.8436em"}},[s("span")])])])])])])])])])])],-1),M=s("p",null,[a("So, the average rate of the reaction between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",{mathvariant:"bold"},"2.54"),s("mo",null,"×"),s("mn",{mathvariant:"bold"},"1"),s("msup",null,[s("mn",{mathvariant:"bold"},"0"),s("mrow",null,[s("mo",null,"−"),s("mn",{mathvariant:"bold"},"3")])]),s("mi",{mathvariant:"normal"},"M"),s("msup",null,[s("mi",{mathvariant:"normal"},"s"),s("mrow",null,[s("mo",null,"−"),s("mn",{mathvariant:"bold"},"1")])])]),s("annotation",{encoding:"application/x-tex"},"\\bold{2.54 \\times 10^{-3} \\mathrm{M} \\mathrm{s}^{-1}}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8974em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathbf"},"2.54"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathbf"},"1"),s("span",{class:"mord"},[s("span",{class:"mord mathbf"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathbf mtight"},"3")])])])])])])])]),s("span",{class:"mord mathrm"},"M"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"s"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathbf mtight"},"1")])])])])])])])])])])])]),a(".")],-1);function _(N,O,L,D,B,P){const l=t;return e(),m("div",null,[p,c(l,{readTime:"2",words:"404"}),r,o,h,g,u,y,d,v,b,x,w,f,k,z,M])}const S=n(i,[["render",_]]);export{q as __pageData,S as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as m,H as c,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const q=JSON.parse('{"title":"Problem: 03-02-1","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-1.md","filePath":"academic/chemistry/problems/03-02-1.md","lastUpdated":1699051935000}'),i={name:"academic/chemistry/problems/03-02-1.md"},p=s("h1",{id:"problem-03-02-1",tabindex:"-1"},[a("Problem: 03-02-1 "),s("a",{class:"header-anchor",href:"#problem-03-02-1","aria-label":'Permalink to "Problem: 03-02-1"'},"​")],-1),r=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),o=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"N")]),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"→"),s("mn",null,"4"),s("msub",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"N"),s("mi",{mathvariant:"normal"},"O")]),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2 \\mathrm{~N}_2 \\mathrm{O}_5(g) \\rightarrow 4 \\mathrm{NO}_2(g)+\\mathrm{O}_2(g) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"N")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"NO")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])])])],-1),h=s("p",null,[a("The decomposition of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5(g)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])]),a(" is represented by the equation above. A sample of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"("),s("mi",null,"g"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5(g)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")")])])]),a(" is monitored as it decomposes, and the concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" as a function of time is recorded. The results are shown in the table below.")],-1),g=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Time (s)"),s("th",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{[N_2O_5]}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathrm mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose"},"]")])])])])])])]),s("tbody",null,[s("tr",null,[s("td",null,"0"),s("td",null,"1.000")]),s("tr",null,[s("td",null,"25.0"),s("td",null,"0.801")]),s("tr",null,[s("td",null,"50.0"),s("td",null,"0.642")]),s("tr",null,[s("td",null,"75.0"),s("td",null,"0.515")])])],-1),u=s("p",null,[a("Calculate the average rate of the reaction between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds.")],-1),y=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),d=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"A")]),s("mo",null,"+"),s("mi",null,"b"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"B")]),s("mo",null,"→"),s("mi",null,"c"),s("mi",{mathvariant:"normal"},"C"),s("mo",null,"+"),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"D")]),s("annotation",{encoding:"application/x-tex"},"a \\mathrm{~A}+b \\mathrm{~B} \\rightarrow c \\mathrm{C}+d \\mathrm{D} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"A")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"B")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"→"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mord mathrm"},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord mathrm"},"D")])])])])],-1),v=s("p",null,"the rate of reaction is defined as",-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mstyle",{mathcolor:"cyan"},[s("mtext",null," rate "),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"a")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"A"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"b")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"B"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"c")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"C"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])]),s("mo",null,"="),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mi",null,"d")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"D"),s("mo",{stretchy:"false"},"]")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])])])]),s("annotation",{encoding:"application/x-tex"},"\\color{cyan}\\text { rate }=-\\frac{1}{a} \\frac{\\Delta[\\mathrm{A}]}{\\Delta t}=-\\frac{1}{b} \\frac{\\Delta[\\mathrm{B}]}{\\Delta t}=+\\frac{1}{c} \\frac{\\Delta[\\mathrm{C}]}{\\Delta t}=+\\frac{1}{d} \\frac{\\Delta[\\mathrm{D}]}{\\Delta t} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"−"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"a")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"A"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"−"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"b")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"B"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"+"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"c")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"C"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel",style:{color:"cyan"}},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord",style:{color:"cyan"}},"+"),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord mathnormal",style:{color:"cyan"}},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mord mathnormal",style:{color:"cyan"}},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{color:"cyan","border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{color:"cyan"}},[s("span",{class:"mord",style:{color:"cyan"}},"Δ"),s("span",{class:"mopen",style:{color:"cyan"}},"["),s("span",{class:"mord mathrm",style:{color:"cyan"}},"D"),s("span",{class:"mclose",style:{color:"cyan"}},"]")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),x=s("p",null,[a("Notice that the rate of change in concentration of each species is divided by its coefficient from the balanced chemical equation ( "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(", "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"b"),s("mo",{separator:"true"},","),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"b, c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(", or "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" ). This ensures that the calculated reaction rate is the same no matter which reactant or product is monitored for changes in concentration. In this case, the monitored species was "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". With that in mind, let's write the reaction rate in terms of the rate of change in concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" :")],-1),w=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mtext",null," rate "),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mrow",null,[s("mo",{fence:"true"},"["),s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")]),s("mo",{fence:"true"},"]")])]),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t")])])]),s("annotation",{encoding:"application/x-tex"},"\\text { rate }=-\\frac{1}{2} \\frac{\\Delta\\left[\\mathrm{N}_2 \\mathrm{O}_5\\right]}{\\Delta t} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.113em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"Δ"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"]")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),f=s("p",null,[a("Since the coefficient for "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" in the balanced equation is 2 , we divided the rate of change in concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" by 2 . Additionally, since "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"normal"},"N"),s("mn",null,"2")]),s("msub",null,[s("mi",{mathvariant:"normal"},"O"),s("mn",null,"5")])]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{N}_2 \\mathrm{O}_5")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"N"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"O"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" is being consumed in the reaction, we included a negative sign in front of the expression.")],-1),k=s("p",null,[a("Now, let's plug in the information from the table to calculate the average reaction rate between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds:")],-1),z=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mtext",null," rate ")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mo",null,"−"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mfrac",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"0.515"),s("mi",null,"M"),s("mo",null,"−"),s("mn",null,"0.642"),s("mi",null,"M"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"75.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",null,"−"),s("mn",null,"50.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mo",{stretchy:"false"},")")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mn",null,"2.54"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"3")])]),s("mi",null,"M"),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"s")]),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} \\text { rate } & =-\\frac{1}{2} \\frac{(0.515 M-0.642 M)}{(75.0 \\mathrm{~s}-50.0 \\mathrm{~s})} \\\\ & =2.54 \\times 10^{-3} M \\mathrm{~s}^{-1} \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"4.1871em","vertical-align":"-1.8436em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3436em"}},[s("span",{style:{top:"-4.3436em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")])])]),s("span",{style:{top:"-2.2434em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.8436em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3436em"}},[s("span",{style:{top:"-4.3436em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"75.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"50.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"0.515"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"0.642"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-2.2434em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2.54"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"3")])])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"s")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.8436em"}},[s("span")])])])])])])])])])])],-1),M=s("p",null,[a("So, the average rate of the reaction between "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"50.0")]),s("annotation",{encoding:"application/x-tex"},"50.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"50.0")])])]),a(" and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"75.0")]),s("annotation",{encoding:"application/x-tex"},"75.0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"75.0")])])]),a(" seconds is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",{mathvariant:"bold"},"2.54"),s("mo",null,"×"),s("mn",{mathvariant:"bold"},"1"),s("msup",null,[s("mn",{mathvariant:"bold"},"0"),s("mrow",null,[s("mo",null,"−"),s("mn",{mathvariant:"bold"},"3")])]),s("mi",{mathvariant:"normal"},"M"),s("msup",null,[s("mi",{mathvariant:"normal"},"s"),s("mrow",null,[s("mo",null,"−"),s("mn",{mathvariant:"bold"},"1")])])]),s("annotation",{encoding:"application/x-tex"},"\\bold{2.54 \\times 10^{-3} \\mathrm{M} \\mathrm{s}^{-1}}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8974em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathbf"},"2.54"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathbf"},"1"),s("span",{class:"mord"},[s("span",{class:"mord mathbf"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathbf mtight"},"3")])])])])])])])]),s("span",{class:"mord mathrm"},"M"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"s"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathbf mtight"},"1")])])])])])])])])])])])]),a(".")],-1);function _(N,O,L,D,B,P){const l=t;return e(),m("div",null,[p,c(l,{readTime:"2",words:"404"}),r,o,h,g,u,y,d,v,b,x,w,f,k,z,M])}const S=n(i,[["render",_]]);export{q as __pageData,S as default}; diff --git a/assets/academic_chemistry_problems_03-02-2.md.26afa053.js b/assets/academic_chemistry_problems_03-02-2.md.a4b8c746.js similarity index 99% rename from assets/academic_chemistry_problems_03-02-2.md.26afa053.js rename to assets/academic_chemistry_problems_03-02-2.md.a4b8c746.js index 61dc227b..d086cbb7 100644 --- a/assets/academic_chemistry_problems_03-02-2.md.26afa053.js +++ b/assets/academic_chemistry_problems_03-02-2.md.a4b8c746.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as n,c as e,H as r,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Y=JSON.parse('{"title":"Problem: 03-02-2","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-2.md","filePath":"academic/chemistry/problems/03-02-2.md","lastUpdated":1695377563000}'),i={name:"academic/chemistry/problems/03-02-2.md"},c=s("h1",{id:"problem-03-02-2",tabindex:"-1"},[a("Problem: 03-02-2 "),s("a",{class:"header-anchor",href:"#problem-03-02-2","aria-label":'Permalink to "Problem: 03-02-2"'},"​")],-1),p=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),o=s("p",null,[a("The rate law for a particular reaction is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"=k[\\mathrm{XY}]^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(". In an experiment, the initial rate of the reaction is determined to be "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),a(" when the initial concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{XY}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")])])])]),a(" is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"L")]),s("annotation",{encoding:"application/x-tex"},"0.40 \\mathrm{~mol} / \\mathrm{L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"L")])])]),a(".")],-1),h=s("ul",null,[s("li",null,[a("What is the value of the rate constant, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(", for the reaction? "),s("ul",{class:"contains-task-list"},[s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.10"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.10 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.10"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.40 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",checked:"",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2.5"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2.5 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2.5"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])])])])],-1),d=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),u=s("p",null,[a("lo tind the value of the rate constant for the reaction, let's first solve the rate law for "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(" :")],-1),g=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k"),s("mo",null,"="),s("mfrac",null,[s("mtext",null," rate "),s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])])])]),s("annotation",{encoding:"application/x-tex"},"k=\\frac{\\text { rate }}{[\\mathrm{XY}]^2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2281em","vertical-align":"-0.936em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2921em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),y=s("p",null,"Next, let's plug in the initial rate and concentration given in the text:",-1),v=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",null,"k")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"L"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mn",null,"2")])])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mn",null,"0.16"),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",{mathvariant:"normal"},"L"),s("mn",null,"2")])])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} k & =\\frac{0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})}{(0.40 \\mathrm{~mol} / \\mathrm{L})^2} \\\\ & =\\frac{0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})}{0.16 \\mathrm{~mol}^2 / \\mathrm{L}^2} \\\\ & =1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s}) \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"6.9284em","vertical-align":"-3.2142em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.7142em"}},[s("span",{style:{top:"-5.7142em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])]),s("span",{style:{top:"-3.0512em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-0.8728em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.2142em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.7142em"}},[s("span",{style:{top:"-5.7142em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-3.0512em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.2116em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8984em"}},[s("span",{style:{top:"-3.1473em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"L"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.0384em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-0.8728em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.2142em"}},[s("span")])])])])])])])])])])],-1),x=s("p",null,[a("So, the value of the rate constant for the reaction is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])],-1);function w(k,b,f,L,M,_){const l=t;return n(),e("div",null,[c,r(l,{readTime:"1",words:"205"}),p,o,h,d,u,g,y,v,x])}const N=m(i,[["render",w]]);export{Y as __pageData,N as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as n,c as e,H as r,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Y=JSON.parse('{"title":"Problem: 03-02-2","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-2.md","filePath":"academic/chemistry/problems/03-02-2.md","lastUpdated":1699051935000}'),i={name:"academic/chemistry/problems/03-02-2.md"},c=s("h1",{id:"problem-03-02-2",tabindex:"-1"},[a("Problem: 03-02-2 "),s("a",{class:"header-anchor",href:"#problem-03-02-2","aria-label":'Permalink to "Problem: 03-02-2"'},"​")],-1),p=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),o=s("p",null,[a("The rate law for a particular reaction is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"=k[\\mathrm{XY}]^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(". In an experiment, the initial rate of the reaction is determined to be "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),a(" when the initial concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{XY}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")])])])]),a(" is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"L")]),s("annotation",{encoding:"application/x-tex"},"0.40 \\mathrm{~mol} / \\mathrm{L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"L")])])]),a(".")],-1),h=s("ul",null,[s("li",null,[a("What is the value of the rate constant, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(", for the reaction? "),s("ul",{class:"contains-task-list"},[s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.10"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.10 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.10"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.40 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",checked:"",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2.5"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2.5 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2.5"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])])])])],-1),d=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),u=s("p",null,[a("lo tind the value of the rate constant for the reaction, let's first solve the rate law for "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(" :")],-1),g=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k"),s("mo",null,"="),s("mfrac",null,[s("mtext",null," rate "),s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])])])]),s("annotation",{encoding:"application/x-tex"},"k=\\frac{\\text { rate }}{[\\mathrm{XY}]^2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2281em","vertical-align":"-0.936em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2921em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),y=s("p",null,"Next, let's plug in the initial rate and concentration given in the text:",-1),v=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",null,"k")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"L"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mn",null,"2")])])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mn",null,"0.16"),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",{mathvariant:"normal"},"L"),s("mn",null,"2")])])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} k & =\\frac{0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})}{(0.40 \\mathrm{~mol} / \\mathrm{L})^2} \\\\ & =\\frac{0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})}{0.16 \\mathrm{~mol}^2 / \\mathrm{L}^2} \\\\ & =1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s}) \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"6.9284em","vertical-align":"-3.2142em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.7142em"}},[s("span",{style:{top:"-5.7142em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])]),s("span",{style:{top:"-3.0512em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-0.8728em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.2142em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.7142em"}},[s("span",{style:{top:"-5.7142em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-3.0512em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.2116em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8984em"}},[s("span",{style:{top:"-3.1473em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"L"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.0384em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-0.8728em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.2142em"}},[s("span")])])])])])])])])])])],-1),x=s("p",null,[a("So, the value of the rate constant for the reaction is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])],-1);function w(k,b,f,L,M,_){const l=t;return n(),e("div",null,[c,r(l,{readTime:"1",words:"205"}),p,o,h,d,u,g,y,v,x])}const N=m(i,[["render",w]]);export{Y as __pageData,N as default}; diff --git a/assets/academic_chemistry_problems_03-02-2.md.26afa053.lean.js b/assets/academic_chemistry_problems_03-02-2.md.a4b8c746.lean.js similarity index 99% rename from assets/academic_chemistry_problems_03-02-2.md.26afa053.lean.js rename to assets/academic_chemistry_problems_03-02-2.md.a4b8c746.lean.js index 61dc227b..d086cbb7 100644 --- a/assets/academic_chemistry_problems_03-02-2.md.26afa053.lean.js +++ b/assets/academic_chemistry_problems_03-02-2.md.a4b8c746.lean.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as n,c as e,H as r,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Y=JSON.parse('{"title":"Problem: 03-02-2","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-2.md","filePath":"academic/chemistry/problems/03-02-2.md","lastUpdated":1695377563000}'),i={name:"academic/chemistry/problems/03-02-2.md"},c=s("h1",{id:"problem-03-02-2",tabindex:"-1"},[a("Problem: 03-02-2 "),s("a",{class:"header-anchor",href:"#problem-03-02-2","aria-label":'Permalink to "Problem: 03-02-2"'},"​")],-1),p=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),o=s("p",null,[a("The rate law for a particular reaction is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"=k[\\mathrm{XY}]^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(". In an experiment, the initial rate of the reaction is determined to be "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),a(" when the initial concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{XY}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")])])])]),a(" is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"L")]),s("annotation",{encoding:"application/x-tex"},"0.40 \\mathrm{~mol} / \\mathrm{L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"L")])])]),a(".")],-1),h=s("ul",null,[s("li",null,[a("What is the value of the rate constant, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(", for the reaction? "),s("ul",{class:"contains-task-list"},[s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.10"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.10 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.10"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.40 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",checked:"",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2.5"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2.5 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2.5"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])])])])],-1),d=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),u=s("p",null,[a("lo tind the value of the rate constant for the reaction, let's first solve the rate law for "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(" :")],-1),g=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k"),s("mo",null,"="),s("mfrac",null,[s("mtext",null," rate "),s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])])])]),s("annotation",{encoding:"application/x-tex"},"k=\\frac{\\text { rate }}{[\\mathrm{XY}]^2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2281em","vertical-align":"-0.936em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2921em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),y=s("p",null,"Next, let's plug in the initial rate and concentration given in the text:",-1),v=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",null,"k")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"L"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mn",null,"2")])])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mn",null,"0.16"),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",{mathvariant:"normal"},"L"),s("mn",null,"2")])])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} k & =\\frac{0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})}{(0.40 \\mathrm{~mol} / \\mathrm{L})^2} \\\\ & =\\frac{0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})}{0.16 \\mathrm{~mol}^2 / \\mathrm{L}^2} \\\\ & =1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s}) \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"6.9284em","vertical-align":"-3.2142em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.7142em"}},[s("span",{style:{top:"-5.7142em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])]),s("span",{style:{top:"-3.0512em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-0.8728em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.2142em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.7142em"}},[s("span",{style:{top:"-5.7142em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-3.0512em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.2116em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8984em"}},[s("span",{style:{top:"-3.1473em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"L"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.0384em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-0.8728em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.2142em"}},[s("span")])])])])])])])])])])],-1),x=s("p",null,[a("So, the value of the rate constant for the reaction is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])],-1);function w(k,b,f,L,M,_){const l=t;return n(),e("div",null,[c,r(l,{readTime:"1",words:"205"}),p,o,h,d,u,g,y,v,x])}const N=m(i,[["render",w]]);export{Y as __pageData,N as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as n,c as e,H as r,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Y=JSON.parse('{"title":"Problem: 03-02-2","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-2.md","filePath":"academic/chemistry/problems/03-02-2.md","lastUpdated":1699051935000}'),i={name:"academic/chemistry/problems/03-02-2.md"},c=s("h1",{id:"problem-03-02-2",tabindex:"-1"},[a("Problem: 03-02-2 "),s("a",{class:"header-anchor",href:"#problem-03-02-2","aria-label":'Permalink to "Problem: 03-02-2"'},"​")],-1),p=s("h2",{id:"question",tabindex:"-1"},[a("Question "),s("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),o=s("p",null,[a("The rate law for a particular reaction is rate "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mi",null,"k"),s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"=k[\\mathrm{XY}]^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(". In an experiment, the initial rate of the reaction is determined to be "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),a(" when the initial concentration of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{XY}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")])])])]),a(" is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"L")]),s("annotation",{encoding:"application/x-tex"},"0.40 \\mathrm{~mol} / \\mathrm{L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"L")])])]),a(".")],-1),h=s("ul",null,[s("li",null,[a("What is the value of the rate constant, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(", for the reaction? "),s("ul",{class:"contains-task-list"},[s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.10"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.10 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.10"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"0.40 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",checked:"",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])]),s("li",{class:"task-list-item"},[s("input",{class:"task-list-item-checkbox",disabled:"",type:"checkbox"}),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2.5"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"2.5 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2.5"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])])])])],-1),d=s("h2",{id:"solution",tabindex:"-1"},[a("Solution "),s("a",{class:"header-anchor",href:"#solution","aria-label":'Permalink to "Solution"'},"​")],-1),u=s("p",null,[a("lo tind the value of the rate constant for the reaction, let's first solve the rate law for "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k")]),s("annotation",{encoding:"application/x-tex"},"k")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])])]),a(" :")],-1),g=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"k"),s("mo",null,"="),s("mfrac",null,[s("mtext",null," rate "),s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mrow",null,[s("mi",{mathvariant:"normal"},"X"),s("mi",{mathvariant:"normal"},"Y")]),s("msup",null,[s("mo",{stretchy:"false"},"]"),s("mn",null,"2")])])])]),s("annotation",{encoding:"application/x-tex"},"k=\\frac{\\text { rate }}{[\\mathrm{XY}]^2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2281em","vertical-align":"-0.936em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2921em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"XY")]),s("span",{class:"mclose"},[s("span",{class:"mclose"},"]"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," rate ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),y=s("p",null,"Next, let's plug in the initial rate and concentration given in the text:",-1),v=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",null,"k")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mn",null,"0.40"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"L"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mn",null,"2")])])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"0.16"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"L"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("mrow",null,[s("mn",null,"0.16"),s("msup",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",{mathvariant:"normal"},"L"),s("mn",null,"2")])])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} k & =\\frac{0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})}{(0.40 \\mathrm{~mol} / \\mathrm{L})^2} \\\\ & =\\frac{0.16 \\mathrm{~mol} /(\\mathrm{L} \\cdot \\mathrm{s})}{0.16 \\mathrm{~mol}^2 / \\mathrm{L}^2} \\\\ & =1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s}) \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"6.9284em","vertical-align":"-3.2142em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.7142em"}},[s("span",{style:{top:"-5.7142em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k")])]),s("span",{style:{top:"-3.0512em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-0.8728em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.2142em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.7142em"}},[s("span",{style:{top:"-5.7142em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"0.40"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-3.0512em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.2116em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8984em"}},[s("span",{style:{top:"-3.1473em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"L"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"0.16"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathrm"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.0384em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-0.8728em"}},[s("span",{class:"pstrut",style:{height:"3.427em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.2142em"}},[s("span")])])])])])])])])])])],-1),x=s("p",null,[a("So, the value of the rate constant for the reaction is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.0"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"m"),s("mi",{mathvariant:"normal"},"o"),s("mi",{mathvariant:"normal"},"l")]),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"s"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"1.0 \\mathrm{~L} /(\\mathrm{mol} \\cdot \\mathrm{s})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.0"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"mol")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"s"),s("span",{class:"mclose"},")")])])])],-1);function w(k,b,f,L,M,_){const l=t;return n(),e("div",null,[c,r(l,{readTime:"1",words:"205"}),p,o,h,d,u,g,y,v,x])}const N=m(i,[["render",w]]);export{Y as __pageData,N as default}; diff --git a/assets/academic_chemistry_problems_03-02-3.md.5c40792d.js b/assets/academic_chemistry_problems_03-02-3.md.152b3eb2.js similarity index 99% rename from assets/academic_chemistry_problems_03-02-3.md.5c40792d.js rename to assets/academic_chemistry_problems_03-02-3.md.152b3eb2.js index 2f175e2c..8c801708 100644 --- a/assets/academic_chemistry_problems_03-02-3.md.5c40792d.js +++ b/assets/academic_chemistry_problems_03-02-3.md.152b3eb2.js @@ -1 +1 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o as n,c as m,H as r,k as a,a as s,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"Problem 03-02-3","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-3.md","filePath":"academic/chemistry/problems/03-02-3.md","lastUpdated":1695377563000}'),i={name:"academic/chemistry/problems/03-02-3.md"},o=a("h1",{id:"problem-03-02-3",tabindex:"-1"},[s("Problem 03-02-3 "),a("a",{class:"header-anchor",href:"#problem-03-02-3","aria-label":'Permalink to "Problem 03-02-3"'},"​")],-1),h=a("h2",{id:"question",tabindex:"-1"},[s("Question "),a("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),p=a("p",{class:"katex-block"},[a("span",{class:"katex-display"},[a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[a("semantics",null,[a("mrow",null,[a("mn",null,"2"),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"+"),a("mn",null,"2"),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"→"),a("mi",{mathvariant:"normal"},"Q"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"+"),a("mn",null,"2"),a("mi",{mathvariant:"normal"},"R"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")")]),a("annotation",{encoding:"application/x-tex"},"2 \\mathrm{X}(g)+2 \\mathrm{Y}(g) \\rightarrow \\mathrm{Q}(g)+2 \\mathrm{R}(g) ")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),a("span",{class:"mrel"},"→"),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord mathrm"},"Q"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm"},"R"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")")])])])])],-1),d=a("p",null,[s("The reaction represented above is found to be second order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"X")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm"},"X")])])]),s(" and first order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"Y")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{Y}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y")])])]),s(".")],-1),g=a("p",null,[s("What happens to the rate of the reaction when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled?")],-1),u=c('

    • It increases by a factor of 4.
    • It decreases by a factor of 2.
    • It decreases by a factor of 4.
    • It does not change.
    ',2),x=a("p",null,[s("To solve this problem, let's first write out the rate law for the reaction. According to the text, the reaction is second order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"X")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm"},"X")])])]),s(" and first order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"Y")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{Y}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y")])])]),s(", so the rate law is rate "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",null,"="),a("mi",null,"k"),a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("msup",null,[a("mo",{stretchy:"false"},"]"),a("mn",null,"2")]),a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"=k[\\mathrm{X}]^2[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.3669em"}}),a("span",{class:"mrel"},"="),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},[a("span",{class:"mclose"},"]"),a("span",{class:"msupsub"},[a("span",{class:"vlist-t"},[a("span",{class:"vlist-r"},[a("span",{class:"vlist",style:{height:"0.8141em"}},[a("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[a("span",{class:"pstrut",style:{height:"2.7em"}}),a("span",{class:"sizing reset-size6 size3 mtight"},[a("span",{class:"mord mtight"},"2")])])])])])])]),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])])],-1),w=a("p",null,[s("Now, let's think about how the rate changes when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled. Since "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is raised to the second power in the rate law, halving "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" decreases the reaction rate by a factor of 4 . Similarly, since "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is raised to the first power, doubling "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" increases the reaction rate by a factor of 2 . Combined, these changes result in the reaction rate decreasing by a factor of 2 overall. So, when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled, the rate of the reaction decreases by a factor of 2 .")],-1);function y(k,f,b,M,v,_){const t=e;return n(),m("div",null,[o,r(t,{readTime:"1",words:"246"}),h,p,d,g,u,x,w])}const S=l(i,[["render",y]]);export{P as __pageData,S as default}; +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o as n,c as m,H as r,k as a,a as s,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"Problem 03-02-3","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-3.md","filePath":"academic/chemistry/problems/03-02-3.md","lastUpdated":1699051935000}'),i={name:"academic/chemistry/problems/03-02-3.md"},o=a("h1",{id:"problem-03-02-3",tabindex:"-1"},[s("Problem 03-02-3 "),a("a",{class:"header-anchor",href:"#problem-03-02-3","aria-label":'Permalink to "Problem 03-02-3"'},"​")],-1),h=a("h2",{id:"question",tabindex:"-1"},[s("Question "),a("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),p=a("p",{class:"katex-block"},[a("span",{class:"katex-display"},[a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[a("semantics",null,[a("mrow",null,[a("mn",null,"2"),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"+"),a("mn",null,"2"),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"→"),a("mi",{mathvariant:"normal"},"Q"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"+"),a("mn",null,"2"),a("mi",{mathvariant:"normal"},"R"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")")]),a("annotation",{encoding:"application/x-tex"},"2 \\mathrm{X}(g)+2 \\mathrm{Y}(g) \\rightarrow \\mathrm{Q}(g)+2 \\mathrm{R}(g) ")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),a("span",{class:"mrel"},"→"),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord mathrm"},"Q"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm"},"R"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")")])])])])],-1),d=a("p",null,[s("The reaction represented above is found to be second order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"X")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm"},"X")])])]),s(" and first order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"Y")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{Y}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y")])])]),s(".")],-1),g=a("p",null,[s("What happens to the rate of the reaction when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled?")],-1),u=c('
    • It increases by a factor of 4.
    • It decreases by a factor of 2.
    • It decreases by a factor of 4.
    • It does not change.

    Solution

    ',2),x=a("p",null,[s("To solve this problem, let's first write out the rate law for the reaction. According to the text, the reaction is second order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"X")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm"},"X")])])]),s(" and first order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"Y")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{Y}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y")])])]),s(", so the rate law is rate "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",null,"="),a("mi",null,"k"),a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("msup",null,[a("mo",{stretchy:"false"},"]"),a("mn",null,"2")]),a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"=k[\\mathrm{X}]^2[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.3669em"}}),a("span",{class:"mrel"},"="),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},[a("span",{class:"mclose"},"]"),a("span",{class:"msupsub"},[a("span",{class:"vlist-t"},[a("span",{class:"vlist-r"},[a("span",{class:"vlist",style:{height:"0.8141em"}},[a("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[a("span",{class:"pstrut",style:{height:"2.7em"}}),a("span",{class:"sizing reset-size6 size3 mtight"},[a("span",{class:"mord mtight"},"2")])])])])])])]),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])])],-1),w=a("p",null,[s("Now, let's think about how the rate changes when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled. Since "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is raised to the second power in the rate law, halving "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" decreases the reaction rate by a factor of 4 . Similarly, since "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is raised to the first power, doubling "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" increases the reaction rate by a factor of 2 . Combined, these changes result in the reaction rate decreasing by a factor of 2 overall. So, when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled, the rate of the reaction decreases by a factor of 2 .")],-1);function y(k,f,b,M,v,_){const t=e;return n(),m("div",null,[o,r(t,{readTime:"1",words:"246"}),h,p,d,g,u,x,w])}const S=l(i,[["render",y]]);export{P as __pageData,S as default}; diff --git a/assets/academic_chemistry_problems_03-02-3.md.5c40792d.lean.js b/assets/academic_chemistry_problems_03-02-3.md.152b3eb2.lean.js similarity index 99% rename from assets/academic_chemistry_problems_03-02-3.md.5c40792d.lean.js rename to assets/academic_chemistry_problems_03-02-3.md.152b3eb2.lean.js index 1e066e5b..53a2133b 100644 --- a/assets/academic_chemistry_problems_03-02-3.md.5c40792d.lean.js +++ b/assets/academic_chemistry_problems_03-02-3.md.152b3eb2.lean.js @@ -1 +1 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o as n,c as m,H as r,k as a,a as s,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"Problem 03-02-3","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-3.md","filePath":"academic/chemistry/problems/03-02-3.md","lastUpdated":1695377563000}'),i={name:"academic/chemistry/problems/03-02-3.md"},o=a("h1",{id:"problem-03-02-3",tabindex:"-1"},[s("Problem 03-02-3 "),a("a",{class:"header-anchor",href:"#problem-03-02-3","aria-label":'Permalink to "Problem 03-02-3"'},"​")],-1),h=a("h2",{id:"question",tabindex:"-1"},[s("Question "),a("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),p=a("p",{class:"katex-block"},[a("span",{class:"katex-display"},[a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[a("semantics",null,[a("mrow",null,[a("mn",null,"2"),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"+"),a("mn",null,"2"),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"→"),a("mi",{mathvariant:"normal"},"Q"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"+"),a("mn",null,"2"),a("mi",{mathvariant:"normal"},"R"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")")]),a("annotation",{encoding:"application/x-tex"},"2 \\mathrm{X}(g)+2 \\mathrm{Y}(g) \\rightarrow \\mathrm{Q}(g)+2 \\mathrm{R}(g) ")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),a("span",{class:"mrel"},"→"),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord mathrm"},"Q"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm"},"R"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")")])])])])],-1),d=a("p",null,[s("The reaction represented above is found to be second order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"X")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm"},"X")])])]),s(" and first order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"Y")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{Y}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y")])])]),s(".")],-1),g=a("p",null,[s("What happens to the rate of the reaction when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled?")],-1),u=c("",2),x=a("p",null,[s("To solve this problem, let's first write out the rate law for the reaction. According to the text, the reaction is second order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"X")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm"},"X")])])]),s(" and first order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"Y")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{Y}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y")])])]),s(", so the rate law is rate "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",null,"="),a("mi",null,"k"),a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("msup",null,[a("mo",{stretchy:"false"},"]"),a("mn",null,"2")]),a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"=k[\\mathrm{X}]^2[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.3669em"}}),a("span",{class:"mrel"},"="),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},[a("span",{class:"mclose"},"]"),a("span",{class:"msupsub"},[a("span",{class:"vlist-t"},[a("span",{class:"vlist-r"},[a("span",{class:"vlist",style:{height:"0.8141em"}},[a("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[a("span",{class:"pstrut",style:{height:"2.7em"}}),a("span",{class:"sizing reset-size6 size3 mtight"},[a("span",{class:"mord mtight"},"2")])])])])])])]),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])])],-1),w=a("p",null,[s("Now, let's think about how the rate changes when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled. Since "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is raised to the second power in the rate law, halving "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" decreases the reaction rate by a factor of 4 . Similarly, since "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is raised to the first power, doubling "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" increases the reaction rate by a factor of 2 . Combined, these changes result in the reaction rate decreasing by a factor of 2 overall. So, when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled, the rate of the reaction decreases by a factor of 2 .")],-1);function y(k,f,b,M,v,_){const t=e;return n(),m("div",null,[o,r(t,{readTime:"1",words:"246"}),h,p,d,g,u,x,w])}const S=l(i,[["render",y]]);export{P as __pageData,S as default}; +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o as n,c as m,H as r,k as a,a as s,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"Problem 03-02-3","description":"","frontmatter":{},"headers":[],"relativePath":"academic/chemistry/problems/03-02-3.md","filePath":"academic/chemistry/problems/03-02-3.md","lastUpdated":1699051935000}'),i={name:"academic/chemistry/problems/03-02-3.md"},o=a("h1",{id:"problem-03-02-3",tabindex:"-1"},[s("Problem 03-02-3 "),a("a",{class:"header-anchor",href:"#problem-03-02-3","aria-label":'Permalink to "Problem 03-02-3"'},"​")],-1),h=a("h2",{id:"question",tabindex:"-1"},[s("Question "),a("a",{class:"header-anchor",href:"#question","aria-label":'Permalink to "Question"'},"​")],-1),p=a("p",{class:"katex-block"},[a("span",{class:"katex-display"},[a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[a("semantics",null,[a("mrow",null,[a("mn",null,"2"),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"+"),a("mn",null,"2"),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"→"),a("mi",{mathvariant:"normal"},"Q"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")"),a("mo",null,"+"),a("mn",null,"2"),a("mi",{mathvariant:"normal"},"R"),a("mo",{stretchy:"false"},"("),a("mi",null,"g"),a("mo",{stretchy:"false"},")")]),a("annotation",{encoding:"application/x-tex"},"2 \\mathrm{X}(g)+2 \\mathrm{Y}(g) \\rightarrow \\mathrm{Q}(g)+2 \\mathrm{R}(g) ")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),a("span",{class:"mrel"},"→"),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord mathrm"},"Q"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mord"},"2"),a("span",{class:"mord mathrm"},"R"),a("span",{class:"mopen"},"("),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),a("span",{class:"mclose"},")")])])])])],-1),d=a("p",null,[s("The reaction represented above is found to be second order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"X")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm"},"X")])])]),s(" and first order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"Y")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{Y}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y")])])]),s(".")],-1),g=a("p",null,[s("What happens to the rate of the reaction when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled?")],-1),u=c("",2),x=a("p",null,[s("To solve this problem, let's first write out the rate law for the reaction. According to the text, the reaction is second order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"X")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm"},"X")])])]),s(" and first order with respect to "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"Y")]),a("annotation",{encoding:"application/x-tex"},"\\mathrm{Y}")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y")])])]),s(", so the rate law is rate "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",null,"="),a("mi",null,"k"),a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("msup",null,[a("mo",{stretchy:"false"},"]"),a("mn",null,"2")]),a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"=k[\\mathrm{X}]^2[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.3669em"}}),a("span",{class:"mrel"},"="),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),a("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},[a("span",{class:"mclose"},"]"),a("span",{class:"msupsub"},[a("span",{class:"vlist-t"},[a("span",{class:"vlist-r"},[a("span",{class:"vlist",style:{height:"0.8141em"}},[a("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[a("span",{class:"pstrut",style:{height:"2.7em"}}),a("span",{class:"sizing reset-size6 size3 mtight"},[a("span",{class:"mord mtight"},"2")])])])])])])]),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])])],-1),w=a("p",null,[s("Now, let's think about how the rate changes when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled. Since "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is raised to the second power in the rate law, halving "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" decreases the reaction rate by a factor of 4 . Similarly, since "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is raised to the first power, doubling "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" increases the reaction rate by a factor of 2 . Combined, these changes result in the reaction rate decreasing by a factor of 2 overall. So, when "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"X"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{X}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm"},"X"),a("span",{class:"mclose"},"]")])])]),s(" is halved and "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mo",{stretchy:"false"},"["),a("mi",{mathvariant:"normal"},"Y"),a("mo",{stretchy:"false"},"]")]),a("annotation",{encoding:"application/x-tex"},"[\\mathrm{Y}]")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),a("span",{class:"mopen"},"["),a("span",{class:"mord mathrm",style:{"margin-right":"0.025em"}},"Y"),a("span",{class:"mclose"},"]")])])]),s(" is doubled, the rate of the reaction decreases by a factor of 2 .")],-1);function y(k,f,b,M,v,_){const t=e;return n(),m("div",null,[o,r(t,{readTime:"1",words:"246"}),h,p,d,g,u,x,w])}const S=l(i,[["render",y]]);export{P as __pageData,S as default}; diff --git a/assets/academic_literature_index.md.72bce40a.js b/assets/academic_literature_index.md.bd51fa1c.js similarity index 92% rename from assets/academic_literature_index.md.72bce40a.js rename to assets/academic_literature_index.md.bd51fa1c.js index 9b5bc786..d6c6d09e 100644 --- a/assets/academic_literature_index.md.72bce40a.js +++ b/assets/academic_literature_index.md.bd51fa1c.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o,c,H as i,k as e,a as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"Welcome to Literature","description":"","frontmatter":{},"headers":[],"relativePath":"academic/literature/index.md","filePath":"academic/literature/index.md","lastUpdated":1695377563000}'),s={name:"academic/literature/index.md"},d=e("h1",{id:"welcome-to-literature",tabindex:"-1"},[n("Welcome to Literature "),e("a",{class:"header-anchor",href:"#welcome-to-literature","aria-label":'Permalink to "Welcome to Literature"'},"​")],-1);function l(m,_,p,u,f,h){const t=a;return o(),c("div",null,[d,i(t,{readTime:"1",words:"3"})])}const P=r(s,[["render",l]]);export{N as __pageData,P as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o,c,H as i,k as e,a as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"Welcome to Literature","description":"","frontmatter":{},"headers":[],"relativePath":"academic/literature/index.md","filePath":"academic/literature/index.md","lastUpdated":1699051935000}'),s={name:"academic/literature/index.md"},d=e("h1",{id:"welcome-to-literature",tabindex:"-1"},[n("Welcome to Literature "),e("a",{class:"header-anchor",href:"#welcome-to-literature","aria-label":'Permalink to "Welcome to Literature"'},"​")],-1);function l(m,_,p,u,f,h){const t=a;return o(),c("div",null,[d,i(t,{readTime:"1",words:"3"})])}const P=r(s,[["render",l]]);export{N as __pageData,P as default}; diff --git a/assets/academic_literature_index.md.72bce40a.lean.js b/assets/academic_literature_index.md.bd51fa1c.lean.js similarity index 92% rename from assets/academic_literature_index.md.72bce40a.lean.js rename to assets/academic_literature_index.md.bd51fa1c.lean.js index 9b5bc786..d6c6d09e 100644 --- a/assets/academic_literature_index.md.72bce40a.lean.js +++ b/assets/academic_literature_index.md.bd51fa1c.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o,c,H as i,k as e,a as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"Welcome to Literature","description":"","frontmatter":{},"headers":[],"relativePath":"academic/literature/index.md","filePath":"academic/literature/index.md","lastUpdated":1695377563000}'),s={name:"academic/literature/index.md"},d=e("h1",{id:"welcome-to-literature",tabindex:"-1"},[n("Welcome to Literature "),e("a",{class:"header-anchor",href:"#welcome-to-literature","aria-label":'Permalink to "Welcome to Literature"'},"​")],-1);function l(m,_,p,u,f,h){const t=a;return o(),c("div",null,[d,i(t,{readTime:"1",words:"3"})])}const P=r(s,[["render",l]]);export{N as __pageData,P as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o,c,H as i,k as e,a as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"Welcome to Literature","description":"","frontmatter":{},"headers":[],"relativePath":"academic/literature/index.md","filePath":"academic/literature/index.md","lastUpdated":1699051935000}'),s={name:"academic/literature/index.md"},d=e("h1",{id:"welcome-to-literature",tabindex:"-1"},[n("Welcome to Literature "),e("a",{class:"header-anchor",href:"#welcome-to-literature","aria-label":'Permalink to "Welcome to Literature"'},"​")],-1);function l(m,_,p,u,f,h){const t=a;return o(),c("div",null,[d,i(t,{readTime:"1",words:"3"})])}const P=r(s,[["render",l]]);export{N as __pageData,P as default}; diff --git a/assets/academic_literature_writing_methods-of-development.md.b70ad7bf.js b/assets/academic_literature_writing_methods-of-development.md.bcfb091e.js similarity index 99% rename from assets/academic_literature_writing_methods-of-development.md.b70ad7bf.js rename to assets/academic_literature_writing_methods-of-development.md.bcfb091e.js index 4665b294..e88fd665 100644 --- a/assets/academic_literature_writing_methods-of-development.md.b70ad7bf.js +++ b/assets/academic_literature_writing_methods-of-development.md.bcfb091e.js @@ -1 +1 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as i,c as n,H as r,k as e,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const z=JSON.parse('{"title":"Patterns of Organization and Methods of Development","description":"Literature methods of development article clip for review","frontmatter":{"title":"Patterns of Organization and Methods of Development","description":"Literature methods of development article clip for review"},"headers":[],"relativePath":"academic/literature/writing/methods-of-development.md","filePath":"academic/literature/writing/methods-of-development.md","lastUpdated":1695377563000}'),h={name:"academic/literature/writing/methods-of-development.md"},d=e("h1",{id:"patterns-of-organization-and-methods-of-development",tabindex:"-1"},[s("Patterns of Organization and Methods of Development "),e("a",{class:"header-anchor",href:"#patterns-of-organization-and-methods-of-development","aria-label":'Permalink to "Patterns of Organization and Methods of Development"'},"​")],-1),c=l('

    Patterns of organization can help your readers follow the ideas within your essay and your paragraphs, but they can also work as methods of development to help you recognize and further develop ideas and relationships in your writing. Here are some strategies that can help you with both organization and development in your essays.

    Major Patterns of Organization

    A fruit pie.

    Read the following sentences:

    • Now take the pie out of the oven and let it cool on the stovetop.
    • Mix the dry ingredients with the liquid ingredients.
    • Set the pie crust aside while you make the filling.

    How did it feel to read the above list? A bit confusing, I would guess. That’s because the steps for making a pie were not well organized, and the steps don’t include enough detail for us to know exactly what we should do. (Like what are the dry and liquid ingredients?) We all know that starting instructions from the beginning and giving each detailed step in the order it should happen is vital to having a good outcome, in this case a yummy pie! But it’s not always so simple to know how to organize or develop ideas, and sometimes there’s more than one way, which complicates things even further.

    First, let’s take a look at a couple of ways to think about organization.

    General to Specific or Specific to General

    It might be useful to think about organizing your topic like a triangle:

    Two triangles. The first is an inverted pyramid for General to Specific, the second is a pyramid for Specific to General.

    The first triangle represents starting with the most general, big picture information first, moving then to more detailed and often more personal information later in the paper. The second triangle represents an organizational structure that starts with the specific, small scale information first and then moves to the more global, big picture stuff.

    For example, if your topic is traffic in Vancouver, British Columbia, an essay that uses the general-to-specific organizational structure might begin this way:

    Many people consider Vancouver, British Columbia, to be a relaxed place to live. They would be shocked to know how bad the traffic is traveling major arteries into the city and even driving around the city itself.

    An essay that uses the specific-to-general structure might start like this:

    Transit is crowded, parking is expensive, and vehicles stop and go through the main streets of the city of Vancouver, British Columbia, and that is just once travelers brave the crowded arteries to enter the city; Vancouver’s traffic problem does not lend itself to the relaxed atmosphere many believe the city to have.

    What’s the difference between these two introductions? And how might they appeal to the intended audience for this essay in different ways? The first introduction is looking at the big picture of the problem and mentions pollution’s impact on all citizens in Portland, while the second introduction focuses on one specific family. The first helps readers see how vast the problem really is, and the second helps connect readers to a real family, making an emotional appeal from the very beginning. Neither introduction is necessarily better. You’ll choose one over the other based on the kind of tone you’d like to create and how you’d like to affect your audience. It’s completely up to you to make this decision.

    Does the Triangle Mean the Essay Keeps Getting More Specific or More Broad until the Very End?

    The triangle is kind of a general guide, meaning you’re allowed to move around within it all you want. For example, it’s possible that each of your paragraphs will be its own triangle, starting with the general or specific and moving out or in. However, if you begin very broadly, it might be effective to end your essay in a more specific, personal way. And if you begin with a personal story, consider ending your essay by touching on the global impact and importance of your topic.

    Are There Other Ways to Think about Organizing My Ideas?

    Yes! Rather than thinking about which of your ideas are most specific or personal or which are more broad or universal, you might consider one of the following ways of organizing your ideas:

    • Most important information first (consider what you want readers to focus on first)
    • Chronological order (the order in time that events take place)
    • Compare and contrast (ideas are organized together because of their relationship to each other)

    The section on Methods of Development, below, offers more detail about some of these organizational patterns, along with some others.

    Choose one of the following topics, and practice writing a few opening sentences like we did above, once using the general-to-specific format and once using the specific-to-general. Which do you like better? What audience would be attracted to which one? Share with peers to see how others tackled this challenge. How would you rewrite their sentences? Why? Discuss your changes and listen to how your peers have revised your sentences. Taking in other people’s ideas will help you see new ways to approach your own writing and thinking.
    Topics:

    • Facing fears
    • Safety in sports
    • Community policing
    • Educating prisoners
    • Sex education

    Methods of Development

    The methods of development covered here are best used as ways to look at what’s already happening in your draft and to consider how you might emphasize or expand on any existing patterns. You might already be familiar with some of these patterns because teachers will sometimes assign them as the purpose for writing an essay. For example, you might have been asked to write a cause-and-effect essay or a comparison-and-contrast essay.

    It’s important to emphasize here that patterns of organization or methods of developing content usually happen naturally as a consequence of the way the writer engages with and organizes information while writing. That is to say, most writers don’t sit down and say, “I think I’ll write a cause-and-effect essay today.” Instead, a writer might be more likely to be interested in a topic, say, the state of drinking water in the local community, and as the writer begins to explore the topic, certain cause-and-effect relationships between environmental pollutants and the community water supply may begin to emerge.

    So if these patterns just occur naturally in writing, what’s the use in knowing about them? Well, sometimes you might be revising a draft and notice that some of your paragraphs are a bit underdeveloped. Maybe they lack a clear topic, or maybe they lack support. In either case, you can look to these common methods of development to find ways to sharpen those vague topics or to add support where needed. Do you have a clear cause statement somewhere but you haven’t explored the effects? Are you lacking detail somewhere where a narrative story or historical chronology can help build reader interest and add support? Are you struggling to define an idea that might benefit from some comparison or contrast? Read on to consider some of the ways that these strategies can help you in revision.

    Cause and Effect (or Effect and Cause)

    Do you see a potential cause-and-effect relationship developing in your draft? The cause-and-effect pattern may be used to identify one or more causes followed by one or more effects or results. Or you may reverse this sequence and describe effects first and then the cause or causes. For example, the causes of water pollution might be followed by its effects on both humans and animals. You may use obvious transitions to clarify cause and effect, such as “What are the results? Here are some of them…” or you might simply use the words cause, effect, and result, to cue the reader about your about the relationships that you’re establishing.

    Problem-Solution

    At some point does your essay explore a problem or suggest a solution? The problem-solution pattern is commonly used in identifying something that’s wrong and in contemplating what might be done to remedy the situation. There are probably more ways to organize a problem-solution approach, but but here are three possibilities:

    • Describe the problem, followed by the solution.
    • Propose the solution first and then describe the problems that motivated it.
    • Or a problem may be followed by several solutions, one of which is selected as the best.

    When the solution is stated at the end of the paper, the pattern is sometimes called the delayed proposal. For a hostile audience, it may be effective to describe the problem, show why other solutions do not work, and finally suggest the favored solution. You can emphasize the words problem and solution to signal these sections of your paper for your reader.

    Chronology or Narrative

    Do you need to develop support for a topic where telling a story can illustrate some important concept for your readers? Material arranged chronologically is explained as it occurs in time. A chronological or narrative method of development might help you find a way to add both interest and content to your essay. Material arranged chronologically is explained as it occurs in time. This pattern may be used to establish what has happened. Chronology or narrative can be a great way to introduce your essay by providing a background or history behind your topic. Or you may want to tell a story to develop one or more points in the body of your essay. You can use transitional words like then, next, and finally to make the parts of the chronology clear.

    Comparison and Contrast

    Are you trying to define something? Do you need your readers to understand what something is and what it is not? The comparison-and-contrast method of development is particularly useful in extending a definition, or anywhere you need to show how a subject is like or unlike another subject. For example, the statement is often made that drug abuse is a medical problem instead of a criminal justice issue. An author might attempt to prove this point by comparing drug addiction to AIDS, cancer, or heart disease to redefine the term “addiction” as a medical problem. A statement in opposition to this idea could just as easily establish contrast by explaining all the ways that addiction is different from what we traditionally understand as an illness. In seeking to establish comparison or contrast in your writing, some words or terms that might be useful are by contrast, in comparison, while, some, and others.

    Summary

    These four methods of development—cause and effect, problem-solution, chronology or narrative, and comparison and contrast—are just a few ways to organize and develop ideas and content in your essays. It’s important to note that they should not be a starting point for writers who want to write something authentic—something that they care deeply about. Instead, they can be a great way to help you look for what’s already happening with your topic or in a draft, to help you to write more, or to help you reorganize some parts of an essay that seem to lack connection or feel disjointed. Look for organizational patterns when you’re reading work by professional writers. Notice where they combine strategies (e.g., a problem-solution pattern that uses cause-and-effect organization, or a comparison-contrast pattern that uses narrative or chronology to develop similarities or differences). Pay attention to how different writers emphasize and develop their main ideas, and use what you find to inspire you in your own writing. Better yet, work on developing completely new patterns of your own.

    Reference

    • This chapter was adapted from “Patterns of Organization and Methods of Development” in The Word on College Reading and Writing by Carol Burnell, Jaime Wood, Monique Babin, Susan Pesznecker, and Nicole Rosevear, which is licensed under a CC BY-NC 4.0 Licence. Adapted by Allison Kilgannon.

    • Peach and lavender pie” by Heather Joan is licensed under a CC BY-NC-ND 2.0 Licence.

    • “General to Specific vs. Specific to General Triangles” by Carol Burnell, Jaime Wood, Monique Babin, Susan Pesznecker, and Nicole Rosevear is under a CC BY-NC 4.0 Licence.

    • Kilgannon, Allison. “Patterns of Organization and Methods of Development.” Opentextbc.ca, 20 Aug. 2021, opentextbc.ca/advancedenglish/chapter/patterns-of-organization-and-methods-of-development/#:~:text=These%20four%20methods%20of%20development.

    ',40);function p(u,m,f,g,y,b){const t=o;return i(),n("div",null,[d,r(t,{readTime:"13",words:"2.2k"}),c])}const _=a(h,[["render",p]]);export{z as __pageData,_ as default}; +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as i,c as n,H as r,k as e,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const z=JSON.parse('{"title":"Patterns of Organization and Methods of Development","description":"Literature methods of development article clip for review","frontmatter":{"title":"Patterns of Organization and Methods of Development","description":"Literature methods of development article clip for review"},"headers":[],"relativePath":"academic/literature/writing/methods-of-development.md","filePath":"academic/literature/writing/methods-of-development.md","lastUpdated":1699051935000}'),h={name:"academic/literature/writing/methods-of-development.md"},d=e("h1",{id:"patterns-of-organization-and-methods-of-development",tabindex:"-1"},[s("Patterns of Organization and Methods of Development "),e("a",{class:"header-anchor",href:"#patterns-of-organization-and-methods-of-development","aria-label":'Permalink to "Patterns of Organization and Methods of Development"'},"​")],-1),c=l('

    Patterns of organization can help your readers follow the ideas within your essay and your paragraphs, but they can also work as methods of development to help you recognize and further develop ideas and relationships in your writing. Here are some strategies that can help you with both organization and development in your essays.

    Major Patterns of Organization

    A fruit pie.

    Read the following sentences:

    • Now take the pie out of the oven and let it cool on the stovetop.
    • Mix the dry ingredients with the liquid ingredients.
    • Set the pie crust aside while you make the filling.

    How did it feel to read the above list? A bit confusing, I would guess. That’s because the steps for making a pie were not well organized, and the steps don’t include enough detail for us to know exactly what we should do. (Like what are the dry and liquid ingredients?) We all know that starting instructions from the beginning and giving each detailed step in the order it should happen is vital to having a good outcome, in this case a yummy pie! But it’s not always so simple to know how to organize or develop ideas, and sometimes there’s more than one way, which complicates things even further.

    First, let’s take a look at a couple of ways to think about organization.

    General to Specific or Specific to General

    It might be useful to think about organizing your topic like a triangle:

    Two triangles. The first is an inverted pyramid for General to Specific, the second is a pyramid for Specific to General.

    The first triangle represents starting with the most general, big picture information first, moving then to more detailed and often more personal information later in the paper. The second triangle represents an organizational structure that starts with the specific, small scale information first and then moves to the more global, big picture stuff.

    For example, if your topic is traffic in Vancouver, British Columbia, an essay that uses the general-to-specific organizational structure might begin this way:

    Many people consider Vancouver, British Columbia, to be a relaxed place to live. They would be shocked to know how bad the traffic is traveling major arteries into the city and even driving around the city itself.

    An essay that uses the specific-to-general structure might start like this:

    Transit is crowded, parking is expensive, and vehicles stop and go through the main streets of the city of Vancouver, British Columbia, and that is just once travelers brave the crowded arteries to enter the city; Vancouver’s traffic problem does not lend itself to the relaxed atmosphere many believe the city to have.

    What’s the difference between these two introductions? And how might they appeal to the intended audience for this essay in different ways? The first introduction is looking at the big picture of the problem and mentions pollution’s impact on all citizens in Portland, while the second introduction focuses on one specific family. The first helps readers see how vast the problem really is, and the second helps connect readers to a real family, making an emotional appeal from the very beginning. Neither introduction is necessarily better. You’ll choose one over the other based on the kind of tone you’d like to create and how you’d like to affect your audience. It’s completely up to you to make this decision.

    Does the Triangle Mean the Essay Keeps Getting More Specific or More Broad until the Very End?

    The triangle is kind of a general guide, meaning you’re allowed to move around within it all you want. For example, it’s possible that each of your paragraphs will be its own triangle, starting with the general or specific and moving out or in. However, if you begin very broadly, it might be effective to end your essay in a more specific, personal way. And if you begin with a personal story, consider ending your essay by touching on the global impact and importance of your topic.

    Are There Other Ways to Think about Organizing My Ideas?

    Yes! Rather than thinking about which of your ideas are most specific or personal or which are more broad or universal, you might consider one of the following ways of organizing your ideas:

    • Most important information first (consider what you want readers to focus on first)
    • Chronological order (the order in time that events take place)
    • Compare and contrast (ideas are organized together because of their relationship to each other)

    The section on Methods of Development, below, offers more detail about some of these organizational patterns, along with some others.

    Choose one of the following topics, and practice writing a few opening sentences like we did above, once using the general-to-specific format and once using the specific-to-general. Which do you like better? What audience would be attracted to which one? Share with peers to see how others tackled this challenge. How would you rewrite their sentences? Why? Discuss your changes and listen to how your peers have revised your sentences. Taking in other people’s ideas will help you see new ways to approach your own writing and thinking.
    Topics:

    • Facing fears
    • Safety in sports
    • Community policing
    • Educating prisoners
    • Sex education

    Methods of Development

    The methods of development covered here are best used as ways to look at what’s already happening in your draft and to consider how you might emphasize or expand on any existing patterns. You might already be familiar with some of these patterns because teachers will sometimes assign them as the purpose for writing an essay. For example, you might have been asked to write a cause-and-effect essay or a comparison-and-contrast essay.

    It’s important to emphasize here that patterns of organization or methods of developing content usually happen naturally as a consequence of the way the writer engages with and organizes information while writing. That is to say, most writers don’t sit down and say, “I think I’ll write a cause-and-effect essay today.” Instead, a writer might be more likely to be interested in a topic, say, the state of drinking water in the local community, and as the writer begins to explore the topic, certain cause-and-effect relationships between environmental pollutants and the community water supply may begin to emerge.

    So if these patterns just occur naturally in writing, what’s the use in knowing about them? Well, sometimes you might be revising a draft and notice that some of your paragraphs are a bit underdeveloped. Maybe they lack a clear topic, or maybe they lack support. In either case, you can look to these common methods of development to find ways to sharpen those vague topics or to add support where needed. Do you have a clear cause statement somewhere but you haven’t explored the effects? Are you lacking detail somewhere where a narrative story or historical chronology can help build reader interest and add support? Are you struggling to define an idea that might benefit from some comparison or contrast? Read on to consider some of the ways that these strategies can help you in revision.

    Cause and Effect (or Effect and Cause)

    Do you see a potential cause-and-effect relationship developing in your draft? The cause-and-effect pattern may be used to identify one or more causes followed by one or more effects or results. Or you may reverse this sequence and describe effects first and then the cause or causes. For example, the causes of water pollution might be followed by its effects on both humans and animals. You may use obvious transitions to clarify cause and effect, such as “What are the results? Here are some of them…” or you might simply use the words cause, effect, and result, to cue the reader about your about the relationships that you’re establishing.

    Problem-Solution

    At some point does your essay explore a problem or suggest a solution? The problem-solution pattern is commonly used in identifying something that’s wrong and in contemplating what might be done to remedy the situation. There are probably more ways to organize a problem-solution approach, but but here are three possibilities:

    • Describe the problem, followed by the solution.
    • Propose the solution first and then describe the problems that motivated it.
    • Or a problem may be followed by several solutions, one of which is selected as the best.

    When the solution is stated at the end of the paper, the pattern is sometimes called the delayed proposal. For a hostile audience, it may be effective to describe the problem, show why other solutions do not work, and finally suggest the favored solution. You can emphasize the words problem and solution to signal these sections of your paper for your reader.

    Chronology or Narrative

    Do you need to develop support for a topic where telling a story can illustrate some important concept for your readers? Material arranged chronologically is explained as it occurs in time. A chronological or narrative method of development might help you find a way to add both interest and content to your essay. Material arranged chronologically is explained as it occurs in time. This pattern may be used to establish what has happened. Chronology or narrative can be a great way to introduce your essay by providing a background or history behind your topic. Or you may want to tell a story to develop one or more points in the body of your essay. You can use transitional words like then, next, and finally to make the parts of the chronology clear.

    Comparison and Contrast

    Are you trying to define something? Do you need your readers to understand what something is and what it is not? The comparison-and-contrast method of development is particularly useful in extending a definition, or anywhere you need to show how a subject is like or unlike another subject. For example, the statement is often made that drug abuse is a medical problem instead of a criminal justice issue. An author might attempt to prove this point by comparing drug addiction to AIDS, cancer, or heart disease to redefine the term “addiction” as a medical problem. A statement in opposition to this idea could just as easily establish contrast by explaining all the ways that addiction is different from what we traditionally understand as an illness. In seeking to establish comparison or contrast in your writing, some words or terms that might be useful are by contrast, in comparison, while, some, and others.

    Summary

    These four methods of development—cause and effect, problem-solution, chronology or narrative, and comparison and contrast—are just a few ways to organize and develop ideas and content in your essays. It’s important to note that they should not be a starting point for writers who want to write something authentic—something that they care deeply about. Instead, they can be a great way to help you look for what’s already happening with your topic or in a draft, to help you to write more, or to help you reorganize some parts of an essay that seem to lack connection or feel disjointed. Look for organizational patterns when you’re reading work by professional writers. Notice where they combine strategies (e.g., a problem-solution pattern that uses cause-and-effect organization, or a comparison-contrast pattern that uses narrative or chronology to develop similarities or differences). Pay attention to how different writers emphasize and develop their main ideas, and use what you find to inspire you in your own writing. Better yet, work on developing completely new patterns of your own.

    Reference

    • This chapter was adapted from “Patterns of Organization and Methods of Development” in The Word on College Reading and Writing by Carol Burnell, Jaime Wood, Monique Babin, Susan Pesznecker, and Nicole Rosevear, which is licensed under a CC BY-NC 4.0 Licence. Adapted by Allison Kilgannon.

    • Peach and lavender pie” by Heather Joan is licensed under a CC BY-NC-ND 2.0 Licence.

    • “General to Specific vs. Specific to General Triangles” by Carol Burnell, Jaime Wood, Monique Babin, Susan Pesznecker, and Nicole Rosevear is under a CC BY-NC 4.0 Licence.

    • Kilgannon, Allison. “Patterns of Organization and Methods of Development.” Opentextbc.ca, 20 Aug. 2021, opentextbc.ca/advancedenglish/chapter/patterns-of-organization-and-methods-of-development/#:~:text=These%20four%20methods%20of%20development.

    ',40);function p(u,m,f,g,y,b){const t=o;return i(),n("div",null,[d,r(t,{readTime:"13",words:"2.2k"}),c])}const _=a(h,[["render",p]]);export{z as __pageData,_ as default}; diff --git a/assets/academic_literature_writing_methods-of-development.md.b70ad7bf.lean.js b/assets/academic_literature_writing_methods-of-development.md.bcfb091e.lean.js similarity index 90% rename from assets/academic_literature_writing_methods-of-development.md.b70ad7bf.lean.js rename to assets/academic_literature_writing_methods-of-development.md.bcfb091e.lean.js index c84bf8ac..7195e202 100644 --- a/assets/academic_literature_writing_methods-of-development.md.b70ad7bf.lean.js +++ b/assets/academic_literature_writing_methods-of-development.md.bcfb091e.lean.js @@ -1 +1 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as i,c as n,H as r,k as e,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const z=JSON.parse('{"title":"Patterns of Organization and Methods of Development","description":"Literature methods of development article clip for review","frontmatter":{"title":"Patterns of Organization and Methods of Development","description":"Literature methods of development article clip for review"},"headers":[],"relativePath":"academic/literature/writing/methods-of-development.md","filePath":"academic/literature/writing/methods-of-development.md","lastUpdated":1695377563000}'),h={name:"academic/literature/writing/methods-of-development.md"},d=e("h1",{id:"patterns-of-organization-and-methods-of-development",tabindex:"-1"},[s("Patterns of Organization and Methods of Development "),e("a",{class:"header-anchor",href:"#patterns-of-organization-and-methods-of-development","aria-label":'Permalink to "Patterns of Organization and Methods of Development"'},"​")],-1),c=l("",40);function p(u,m,f,g,y,b){const t=o;return i(),n("div",null,[d,r(t,{readTime:"13",words:"2.2k"}),c])}const _=a(h,[["render",p]]);export{z as __pageData,_ as default}; +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as i,c as n,H as r,k as e,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const z=JSON.parse('{"title":"Patterns of Organization and Methods of Development","description":"Literature methods of development article clip for review","frontmatter":{"title":"Patterns of Organization and Methods of Development","description":"Literature methods of development article clip for review"},"headers":[],"relativePath":"academic/literature/writing/methods-of-development.md","filePath":"academic/literature/writing/methods-of-development.md","lastUpdated":1699051935000}'),h={name:"academic/literature/writing/methods-of-development.md"},d=e("h1",{id:"patterns-of-organization-and-methods-of-development",tabindex:"-1"},[s("Patterns of Organization and Methods of Development "),e("a",{class:"header-anchor",href:"#patterns-of-organization-and-methods-of-development","aria-label":'Permalink to "Patterns of Organization and Methods of Development"'},"​")],-1),c=l("",40);function p(u,m,f,g,y,b){const t=o;return i(),n("div",null,[d,r(t,{readTime:"13",words:"2.2k"}),c])}const _=a(h,[["render",p]]);export{z as __pageData,_ as default}; diff --git a/assets/academic_physics_index.md.62b4f030.js b/assets/academic_physics_index.md.6ec0ff5a.js similarity index 92% rename from assets/academic_physics_index.md.62b4f030.js rename to assets/academic_physics_index.md.6ec0ff5a.js index a19c6e53..dde4619c 100644 --- a/assets/academic_physics_index.md.62b4f030.js +++ b/assets/academic_physics_index.md.6ec0ff5a.js @@ -1 +1 @@ -import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as c,c as o,H as i,k as e,a as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Welcome to Physics","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/index.md","filePath":"academic/physics/index.md","lastUpdated":1695377563000}'),n={name:"academic/physics/index.md"},d=e("h1",{id:"welcome-to-physics",tabindex:"-1"},[r("Welcome to Physics "),e("a",{class:"header-anchor",href:"#welcome-to-physics","aria-label":'Permalink to "Welcome to Physics"'},"​")],-1);function m(p,l,_,h,f,x){const a=s;return c(),o("div",null,[d,i(a,{readTime:"1",words:"3"})])}const k=t(n,[["render",m]]);export{$ as __pageData,k as default}; +import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as c,c as o,H as i,k as e,a as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Welcome to Physics","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/index.md","filePath":"academic/physics/index.md","lastUpdated":1699051935000}'),n={name:"academic/physics/index.md"},d=e("h1",{id:"welcome-to-physics",tabindex:"-1"},[r("Welcome to Physics "),e("a",{class:"header-anchor",href:"#welcome-to-physics","aria-label":'Permalink to "Welcome to Physics"'},"​")],-1);function m(p,l,_,h,f,x){const a=s;return c(),o("div",null,[d,i(a,{readTime:"1",words:"3"})])}const k=t(n,[["render",m]]);export{$ as __pageData,k as default}; diff --git a/assets/academic_physics_index.md.62b4f030.lean.js b/assets/academic_physics_index.md.6ec0ff5a.lean.js similarity index 92% rename from assets/academic_physics_index.md.62b4f030.lean.js rename to assets/academic_physics_index.md.6ec0ff5a.lean.js index a19c6e53..dde4619c 100644 --- a/assets/academic_physics_index.md.62b4f030.lean.js +++ b/assets/academic_physics_index.md.6ec0ff5a.lean.js @@ -1 +1 @@ -import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as c,c as o,H as i,k as e,a as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Welcome to Physics","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/index.md","filePath":"academic/physics/index.md","lastUpdated":1695377563000}'),n={name:"academic/physics/index.md"},d=e("h1",{id:"welcome-to-physics",tabindex:"-1"},[r("Welcome to Physics "),e("a",{class:"header-anchor",href:"#welcome-to-physics","aria-label":'Permalink to "Welcome to Physics"'},"​")],-1);function m(p,l,_,h,f,x){const a=s;return c(),o("div",null,[d,i(a,{readTime:"1",words:"3"})])}const k=t(n,[["render",m]]);export{$ as __pageData,k as default}; +import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as c,c as o,H as i,k as e,a as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Welcome to Physics","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/index.md","filePath":"academic/physics/index.md","lastUpdated":1699051935000}'),n={name:"academic/physics/index.md"},d=e("h1",{id:"welcome-to-physics",tabindex:"-1"},[r("Welcome to Physics "),e("a",{class:"header-anchor",href:"#welcome-to-physics","aria-label":'Permalink to "Welcome to Physics"'},"​")],-1);function m(p,l,_,h,f,x){const a=s;return c(),o("div",null,[d,i(a,{readTime:"1",words:"3"})])}const k=t(n,[["render",m]]);export{$ as __pageData,k as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_1.md.fa61cf48.js b/assets/academic_physics_ipho-formulas-jpn_1.md.b1c8984c.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_1.md.fa61cf48.js rename to assets/academic_physics_ipho-formulas-jpn_1.md.b1c8984c.js index 1d589bad..ba4e83cc 100644 --- a/assets/academic_physics_ipho-formulas-jpn_1.md.fa61cf48.js +++ b/assets/academic_physics_ipho-formulas-jpn_1.md.b1c8984c.js @@ -1,4 +1,4 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,C as i,o as p,c,H as l,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const as=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 1","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/1.md","filePath":"academic/physics/ipho-formulas-jpn/1.md","lastUpdated":1695377563000}'),h={name:"academic/physics/ipho-formulas-jpn/1.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-1",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 1 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-1","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 1"'},"​")],-1),g=s("h2",{id:"_1-数学",tabindex:"-1"},[a("1: 数学 "),s("a",{class:"header-anchor",href:"#_1-数学","aria-label":'Permalink to "1: 数学"'},"​")],-1),u=s("h3",{id:"_1-1-taylor-展開",tabindex:"-1"},[a("1.1: Taylor 展開 "),s("a",{class:"header-anchor",href:"#_1-1-taylor-展開","aria-label":'Permalink to "1.1: Taylor 展開"'},"​")],-1),y=s("ol",null,[s("li",null,[s("p",null,"Taylor 展開(アバウトに切り捨てる:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"F"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("mo",null,"∑"),s("msup",null,[s("mi",null,"F"),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mo",{stretchy:"false"},")")])]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mi",null,"n")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"F(x)=F\\left(x_{0}\\right)+\\sum F^{(n)}\\left(x_{0}\\right)\\left(x-x_{0}\\right)^{n} / n ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mopen mtight"},"("),s("span",{class:"mord mathnormal mtight"},"n"),s("span",{class:"mclose mtight"},")")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8043em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"n")])])])])]),s("p",null,"線形近似(特別な場合):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"≈"),s("mi",null,"F"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"F"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"F(x) \\approx F\\left(x_{0}\\right)+F^{\\prime}\\left(x_{0}\\right)\\left(x-x_{0}\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0519em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8019em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])]),s("p",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"x"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"≪"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"|x| \\ll 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])]),a(" のときの例 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":")]),s("annotation",{encoding:"application/x-tex"},":")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"x"),s("mo",null,"≈"),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"x"),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"e"),s("mi",null,"x")]),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"\\sin x \\approx x, \\cos x \\approx 1-x^{2} / 2, e^{x} \\approx 1+x ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6679em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6776em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])]),s("span",{class:"mord"},"/2"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x")])])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ln"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"≈"),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"n")]),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"n"),s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"\\ln (1+x) \\approx x,(1+x)^{n} \\approx 1+n x ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"ln"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal"},"x")])])])])])])],-1),d=s("h3",{id:"_1-2-摂動法",tabindex:"-1"},[a("1.2: 摂動法 "),s("a",{class:"header-anchor",href:"#_1-2-摂動法","aria-label":'Permalink to "1.2: 摂動法"'},"​")],-1),v=s("ol",{start:"2"},[s("li",null,[a("摂動法:摂動のない(直接解ける)問題の解を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" 番目の近似値として求め,前の似値に基づく次の近似値の補正を繰り返して解を求める.")])],-1),b=s("h3",{id:"_1-3-定数係数線形微分方程式",tabindex:"-1"},[a("1.3: 定数係数線形微分方程式 "),s("a",{class:"header-anchor",href:"#_1-3-定数係数線形微分方程式","aria-label":'Permalink to "1.3: 定数係数線形微分方程式"'},"​")],-1),x=s("ol",{start:"3"},[s("li",null,[s("p",null,[a("定数係数線形微分方程式 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("msup",null,[s("mi",null,"y"),s("mrow",null,[s("mo",{mathvariant:"normal"},"′"),s("mo",{mathvariant:"normal"},"′")])]),s("mo",null,"+"),s("mi",null,"b"),s("msup",null,[s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"+"),s("mi",null,"c"),s("mi",null,"y"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"a y^{\\prime \\prime}+b y^{\\prime}+c y=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9463em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9463em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"cy"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" の解:")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"="),s("mi",null,"A"),s("mi",null,"exp"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"λ"),s("mn",null,"1")]),s("mi",null,"x"),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("mi",null,"B"),s("mi",null,"exp"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"λ"),s("mn",null,"2")]),s("mi",null,"x"),s("mo",{fence:"true"},")")]),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"y=A \\exp \\left(\\lambda_1 x\\right)+B \\exp \\left(\\lambda_2 x\\right) \\text {. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"exp"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"exp"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])]),s("p",null,[a("ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"λ"),s("mrow",null,[s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2")])])]),s("annotation",{encoding:"application/x-tex"},"\\lambda_{1,2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(" は特性方程式 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("msup",null,[s("mi",null,"λ"),s("mn",null,"2")]),s("mo",null,"+"),s("mi",null,"b"),s("mi",null,"λ"),s("mo",null,"+"),s("mi",null,"c"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"a \\lambda^2+b \\lambda+c=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8974em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"bλ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" の異な る 2 解. もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mo",{separator:"true"},","),s("mi",null,"b"),s("mo",{separator:"true"},","),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"a, b, c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(" が実数で特性方程式の解が複素数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"λ"),s("mrow",null,[s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2")])]),s("mo",null,"="),s("mi",null,"γ"),s("mo",null,"±"),s("mi",null,"i"),s("mi",null,"ω")]),s("annotation",{encoding:"application/x-tex"},"\\lambda_{1,2}=\\gamma \\pm i \\omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω")])])]),a(" ならば,")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"="),s("mi",null,"C"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"γ"),s("mi",null,"x")])]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"ω"),s("mi",null,"x"),s("mo",null,"+"),s("msub",null,[s("mi",null,"φ"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"y=C e^{\\gamma x} \\sin \\left(\\omega x+\\varphi_0\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord mathnormal mtight"},"x")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])])])],-1),z=s("h3",{id:"_1-4-複素数",tabindex:"-1"},[a("1.4: 複素数 "),s("a",{class:"header-anchor",href:"#_1-4-複素数","aria-label":'Permalink to "1.4: 複素数"'},"​")],-1),f=s("ol",{start:"4"},[s("li",null,[s("p",null,"複素数"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"z"),s("mo",null,"="),s("mi",null,"a"),s("mo",null,"+"),s("mi",null,"b"),s("mi",null,"i"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",{separator:"true"},","),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",null,"="),s("mi",null,"a"),s("mo",null,"−"),s("mi",null,"b"),s("mi",null,"i"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("msup",null,[s("mi",{mathvariant:"normal"},"∣"),s("mn",null,"2")]),s("mo",null,"="),s("mi",null,"z"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",null,"="),s("msup",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"φ"),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mfrac",null,[s("mi",null,"b"),s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"Re"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"z"),s("mo",null,"+"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Im"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"z"),s("mo",null,"−"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"i")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",{fence:"true"},"∣")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("mo",{fence:"true"},"∣")]),s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",{fence:"true"},"∣")]),s("mo",{separator:"true"},","),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("mo",null,"+"),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"="),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"+"),s("mi",null,"i"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"+"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"−"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"i")])])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} z=a+b i=|z| e^{i \\varphi}, \\bar{z}=a-b i=|z| e^{-i \\varphi} \\\\ |z|^2=z \\bar{z}=a^2+b^2, \\varphi=\\arg z=\\arcsin \\frac{b}{|z|} \\\\ \\operatorname{Re} z=(z+\\bar{z}) / 2, \\operatorname{Im} z=(z-\\bar{z}) / 2 i \\\\ \\left|z_1 z_2\\right|=\\left|z_1\\right|\\left|z_2\\right|, \\arg z_1 z_2=\\arg z_1+\\arg z_2 \\\\ e^{i \\varphi}=\\cos \\varphi+i \\sin \\varphi \\\\ \\cos \\varphi=\\frac{e^{i \\varphi}+e^{-i \\varphi}}{2}, \\sin \\varphi=\\frac{e^{i \\varphi}-e^{-i \\varphi}}{2 i} \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.1644em","vertical-align":"-5.3322em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8322em"}},[s("span",{style:{top:"-8.4592em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"bi"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"bi"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])]),s("span",{style:{top:"-6.4278em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-4.3518em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"Re")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/2"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"Im")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"i")])]),s("span",{style:{top:"-2.8518em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-1.3171em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])]),s("span",{style:{top:"0.8446em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5017em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5017em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"i")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.3322em"}},[s("span")])])])])])])])])])])])])],-1),w=s("h3",{id:"_1-5-ベクトルの内積と外積",tabindex:"-1"},[a("1.5: ベクトルの内積と外積 "),s("a",{class:"header-anchor",href:"#_1-5-ベクトルの内積と外積","aria-label":'Permalink to "1.5: ベクトルの内積と外積"'},"​")],-1),k=s("ol",{start:"5"},[s("li",null,[s("p",null,[a("ベクトルの内積と外積は分配法則が成立する : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mo",{stretchy:"false"},"("),s("mi",null,"b"),s("mo",null,"+"),s("mi",null,"c"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mo",null,"+"),s("mi",null,"a"),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"a(b+c)=a b+a c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord mathnormal"},"c")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"="),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"x")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"a"),s("mi",null,"y")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"y")]),s("mo",null,"+"),s("mo",null,"⋯"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mo",null,"−"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⊥"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"b")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"a"),s("mi",null,"y")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"z")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"a"),s("mi",null,"z")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"y")]),s("mo",{fence:"true"},")")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"x")]),s("mo",null,"+"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"a"),s("mi",null,"z")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"x")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"z")]),s("mo",{fence:"true"},")")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"y")]),s("mo",null,"+"),s("mo",null,"⋯")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},"]"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"−"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"bold-italic"},"c")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{a} \\cdot \\boldsymbol{b}=\\boldsymbol{b} \\cdot \\boldsymbol{a}=a_x b_x+a_y b_y+\\cdots=a b \\cos \\varphi \\\\ |\\boldsymbol{a} \\times \\boldsymbol{b}|=a b \\sin \\varphi, \\boldsymbol{a} \\times \\boldsymbol{b}=-\\boldsymbol{b} \\times \\boldsymbol{a} \\perp \\boldsymbol{a}, \\boldsymbol{b} \\\\ \\boldsymbol{a} \\times \\boldsymbol{b}=\\left(a_y b_z-a_z b_y\\right) \\boldsymbol{e}_x+\\left(a_z b_x-a_x b_z\\right) \\boldsymbol{e}_y+\\cdots \\\\ \\boldsymbol{a} \\times[\\boldsymbol{b} \\times \\boldsymbol{c}]=(\\boldsymbol{a} \\cdot \\boldsymbol{c}) \\boldsymbol{b}-(\\boldsymbol{a} \\cdot \\boldsymbol{b}) \\boldsymbol{c} \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"6em","vertical-align":"-2.75em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.25em"}},[s("span",{style:{top:"-5.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},"⋯"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])]),s("span",{style:{top:"-3.91em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])])])]),s("span",{style:{top:"-2.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},"⋯")])]),s("span",{style:{top:"-0.91em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.75em"}},[s("span")])])])])])])])])])])]),s("p",null,"スカラー三重積(3 つのベクトルで張られる平行四面 体の体積):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},")"),s("mo",null,"≡"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},"]"),s("mo",null,"="),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{stretchy:"false"},"]"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(\\boldsymbol{a}, \\boldsymbol{b}, \\boldsymbol{c}) \\equiv \\boldsymbol{a} \\cdot[\\boldsymbol{b} \\times \\boldsymbol{c}]=[\\boldsymbol{a} \\times \\boldsymbol{b}] \\cdot \\boldsymbol{c}=(\\boldsymbol{b}, \\boldsymbol{c}, \\boldsymbol{a}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≡"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4445em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mclose"},")")])])])])])])],-1),_=s("h3",{id:"_1-6-余弦定理と正弦定理",tabindex:"-1"},[a("1.6: 余弦定理と正弦定理 "),s("a",{class:"header-anchor",href:"#_1-6-余弦定理と正弦定理","aria-label":'Permalink to "1.6: 余弦定理と正弦定理"'},"​")],-1),M=s("ol",{start:"6"},[s("li",null,[a("余弦定理と正弦定理:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")]),s("mo",null,"="),s("msup",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")]),s("mo",null,"−"),s("mn",null,"2"),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"C")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"a"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"A"),s("mo",null,"="),s("mi",null,"b"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"B"),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"R")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & c^2=a^2+b^2-2 a b \\cos C \\\\ & a / \\sin A=b / \\sin B=2 R \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.7621em"}},[s("span",{class:"pstrut",style:{height:"2.8641em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.2621em"}},[s("span",{class:"pstrut",style:{height:"2.8641em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.8979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),L=s("h3",{id:"_1-7-三角法",tabindex:"-1"},[a("1.7: 三角法 "),s("a",{class:"header-anchor",href:"#_1-7-三角法","aria-label":'Permalink to "1.7: 三角法"'},"​")],-1),P=s("ol",{start:"7"},[s("li",null,[s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"±"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"β")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"∓"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"β")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"∓"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",{stretchy:"false"},")")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mi",null,"α"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mn",null,"2"),s("mi",null,"α")]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("msup",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mi",null,"α"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mn",null,"2"),s("mi",null,"α")]),s("mn",null,"2")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"−"),s("mi",null,"β"),s("mo",{stretchy:"false"},")")]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mo",null,"…")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"="),s("mn",null,"2"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"cos"),s("mo",null,"⁡"),s("mfrac",null,[s("mrow",null,[s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"β")]),s("mn",null,"2")]),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mfrac",null,[s("mrow",null,[s("mi",null,"α"),s("mo",null,"−"),s("mi",null,"β")]),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("mo",null,"…")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\sin (\\alpha \\pm \\beta)=\\sin \\alpha \\cos \\beta \\pm \\cos \\alpha \\sin \\beta \\\\ & \\cos (\\alpha \\pm \\beta)=\\cos \\alpha \\cos \\beta \\mp \\sin \\alpha \\sin \\beta \\\\ & \\tan (\\alpha \\pm \\beta)=(\\tan \\alpha \\pm \\tan \\beta) /(1 \\mp \\tan \\alpha \\tan \\beta) \\\\ & \\cos ^2 \\alpha=\\frac{1+\\cos 2 \\alpha}{2}, \\sin ^2 \\alpha=\\frac{1-\\cos 2 \\alpha}{2} \\\\ & \\cos \\alpha \\cos \\beta=\\frac{\\cos (\\alpha+\\beta)+\\cos (\\alpha-\\beta)}{2}, \\ldots \\\\ & \\cos \\alpha+\\cos \\beta=2\\left(\\cos \\frac{\\alpha+\\beta}{2}+\\cos \\frac{\\alpha-\\beta}{2}\\right), \\ldots \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.9205em","vertical-align":"-5.7102em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.2102em"}},[s("span",{style:{top:"-8.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-7.3202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-5.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-3.8388em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.4258em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"1.0102em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.7102em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.2102em"}},[s("span",{style:{top:"-8.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])]),s("span",{style:{top:"-7.3202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∓"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])]),s("span",{style:{top:"-5.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∓"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-3.8388em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"cos"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"sin"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8719em"}},[s("span",{style:{top:"-3.1208em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-1.4258em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"…")])]),s("span",{style:{top:"1.0102em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"…")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.7102em"}},[s("span")])])])])])])])])])])])])],-1),F=r('

    1.8: 円周角

    1. 円周角は中心角の半分. よって,直角三角形の斜辺は その外接円の直径. もし四角形の対角の和が 180 度な らば,それは円に内接する.

    1.9: 三角形の面樍

    ',3),A=s("ol",{start:"9"},[s("li",null,[a("三角形の面樍 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mi",null,"a"),s("msub",null,[s("mi",null,"h"),s("mi",null,"a")]),s("mo",null,"="),s("mi",null,"p"),s("mi",null,"r"),s("mo",null,"="),s("msqrt",null,[s("mrow",null,[s("mi",null,"p"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"a"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"b"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"c"),s("mo",{stretchy:"false"},")")])]),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"c"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"4"),s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"=\\frac{1}{2} a h_a=p r=\\sqrt{p(p-a)(p-b)(p-c)}=a b c / 4 R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1901em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"h"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"a")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,C as i,o as p,c,H as l,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const as=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 1","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/1.md","filePath":"academic/physics/ipho-formulas-jpn/1.md","lastUpdated":1699051935000}'),h={name:"academic/physics/ipho-formulas-jpn/1.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-1",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 1 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-1","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 1"'},"​")],-1),g=s("h2",{id:"_1-数学",tabindex:"-1"},[a("1: 数学 "),s("a",{class:"header-anchor",href:"#_1-数学","aria-label":'Permalink to "1: 数学"'},"​")],-1),u=s("h3",{id:"_1-1-taylor-展開",tabindex:"-1"},[a("1.1: Taylor 展開 "),s("a",{class:"header-anchor",href:"#_1-1-taylor-展開","aria-label":'Permalink to "1.1: Taylor 展開"'},"​")],-1),y=s("ol",null,[s("li",null,[s("p",null,"Taylor 展開(アバウトに切り捨てる:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"F"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("mo",null,"∑"),s("msup",null,[s("mi",null,"F"),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mo",{stretchy:"false"},")")])]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mi",null,"n")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"F(x)=F\\left(x_{0}\\right)+\\sum F^{(n)}\\left(x_{0}\\right)\\left(x-x_{0}\\right)^{n} / n ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mopen mtight"},"("),s("span",{class:"mord mathnormal mtight"},"n"),s("span",{class:"mclose mtight"},")")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8043em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"n")])])])])]),s("p",null,"線形近似(特別な場合):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"≈"),s("mi",null,"F"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"F"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"F(x) \\approx F\\left(x_{0}\\right)+F^{\\prime}\\left(x_{0}\\right)\\left(x-x_{0}\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0519em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8019em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])]),s("p",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"x"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"≪"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"|x| \\ll 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])]),a(" のときの例 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":")]),s("annotation",{encoding:"application/x-tex"},":")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"x"),s("mo",null,"≈"),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"x"),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"e"),s("mi",null,"x")]),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"\\sin x \\approx x, \\cos x \\approx 1-x^{2} / 2, e^{x} \\approx 1+x ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6679em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6776em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])]),s("span",{class:"mord"},"/2"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x")])])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ln"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"≈"),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"n")]),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"n"),s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"\\ln (1+x) \\approx x,(1+x)^{n} \\approx 1+n x ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"ln"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal"},"x")])])])])])])],-1),d=s("h3",{id:"_1-2-摂動法",tabindex:"-1"},[a("1.2: 摂動法 "),s("a",{class:"header-anchor",href:"#_1-2-摂動法","aria-label":'Permalink to "1.2: 摂動法"'},"​")],-1),v=s("ol",{start:"2"},[s("li",null,[a("摂動法:摂動のない(直接解ける)問題の解を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" 番目の近似値として求め,前の似値に基づく次の近似値の補正を繰り返して解を求める.")])],-1),b=s("h3",{id:"_1-3-定数係数線形微分方程式",tabindex:"-1"},[a("1.3: 定数係数線形微分方程式 "),s("a",{class:"header-anchor",href:"#_1-3-定数係数線形微分方程式","aria-label":'Permalink to "1.3: 定数係数線形微分方程式"'},"​")],-1),x=s("ol",{start:"3"},[s("li",null,[s("p",null,[a("定数係数線形微分方程式 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("msup",null,[s("mi",null,"y"),s("mrow",null,[s("mo",{mathvariant:"normal"},"′"),s("mo",{mathvariant:"normal"},"′")])]),s("mo",null,"+"),s("mi",null,"b"),s("msup",null,[s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"+"),s("mi",null,"c"),s("mi",null,"y"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"a y^{\\prime \\prime}+b y^{\\prime}+c y=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9463em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9463em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"cy"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" の解:")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"="),s("mi",null,"A"),s("mi",null,"exp"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"λ"),s("mn",null,"1")]),s("mi",null,"x"),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("mi",null,"B"),s("mi",null,"exp"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"λ"),s("mn",null,"2")]),s("mi",null,"x"),s("mo",{fence:"true"},")")]),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"y=A \\exp \\left(\\lambda_1 x\\right)+B \\exp \\left(\\lambda_2 x\\right) \\text {. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"exp"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"exp"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])]),s("p",null,[a("ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"λ"),s("mrow",null,[s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2")])])]),s("annotation",{encoding:"application/x-tex"},"\\lambda_{1,2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(" は特性方程式 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("msup",null,[s("mi",null,"λ"),s("mn",null,"2")]),s("mo",null,"+"),s("mi",null,"b"),s("mi",null,"λ"),s("mo",null,"+"),s("mi",null,"c"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"a \\lambda^2+b \\lambda+c=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8974em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"bλ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" の異な る 2 解. もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mo",{separator:"true"},","),s("mi",null,"b"),s("mo",{separator:"true"},","),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"a, b, c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(" が実数で特性方程式の解が複素数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"λ"),s("mrow",null,[s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2")])]),s("mo",null,"="),s("mi",null,"γ"),s("mo",null,"±"),s("mi",null,"i"),s("mi",null,"ω")]),s("annotation",{encoding:"application/x-tex"},"\\lambda_{1,2}=\\gamma \\pm i \\omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω")])])]),a(" ならば,")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"="),s("mi",null,"C"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"γ"),s("mi",null,"x")])]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"ω"),s("mi",null,"x"),s("mo",null,"+"),s("msub",null,[s("mi",null,"φ"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"y=C e^{\\gamma x} \\sin \\left(\\omega x+\\varphi_0\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord mathnormal mtight"},"x")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])])])],-1),z=s("h3",{id:"_1-4-複素数",tabindex:"-1"},[a("1.4: 複素数 "),s("a",{class:"header-anchor",href:"#_1-4-複素数","aria-label":'Permalink to "1.4: 複素数"'},"​")],-1),f=s("ol",{start:"4"},[s("li",null,[s("p",null,"複素数"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"z"),s("mo",null,"="),s("mi",null,"a"),s("mo",null,"+"),s("mi",null,"b"),s("mi",null,"i"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",{separator:"true"},","),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",null,"="),s("mi",null,"a"),s("mo",null,"−"),s("mi",null,"b"),s("mi",null,"i"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("msup",null,[s("mi",{mathvariant:"normal"},"∣"),s("mn",null,"2")]),s("mo",null,"="),s("mi",null,"z"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",null,"="),s("msup",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"φ"),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mfrac",null,[s("mi",null,"b"),s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"Re"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"z"),s("mo",null,"+"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Im"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"z"),s("mo",null,"−"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"i")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",{fence:"true"},"∣")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("mo",{fence:"true"},"∣")]),s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",{fence:"true"},"∣")]),s("mo",{separator:"true"},","),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("mo",null,"+"),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"="),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"+"),s("mi",null,"i"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"+"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"−"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"i")])])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} z=a+b i=|z| e^{i \\varphi}, \\bar{z}=a-b i=|z| e^{-i \\varphi} \\\\ |z|^2=z \\bar{z}=a^2+b^2, \\varphi=\\arg z=\\arcsin \\frac{b}{|z|} \\\\ \\operatorname{Re} z=(z+\\bar{z}) / 2, \\operatorname{Im} z=(z-\\bar{z}) / 2 i \\\\ \\left|z_1 z_2\\right|=\\left|z_1\\right|\\left|z_2\\right|, \\arg z_1 z_2=\\arg z_1+\\arg z_2 \\\\ e^{i \\varphi}=\\cos \\varphi+i \\sin \\varphi \\\\ \\cos \\varphi=\\frac{e^{i \\varphi}+e^{-i \\varphi}}{2}, \\sin \\varphi=\\frac{e^{i \\varphi}-e^{-i \\varphi}}{2 i} \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.1644em","vertical-align":"-5.3322em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8322em"}},[s("span",{style:{top:"-8.4592em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"bi"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"bi"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])]),s("span",{style:{top:"-6.4278em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-4.3518em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"Re")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/2"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"Im")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"i")])]),s("span",{style:{top:"-2.8518em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-1.3171em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])]),s("span",{style:{top:"0.8446em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5017em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5017em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"i")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.3322em"}},[s("span")])])])])])])])])])])])])],-1),w=s("h3",{id:"_1-5-ベクトルの内積と外積",tabindex:"-1"},[a("1.5: ベクトルの内積と外積 "),s("a",{class:"header-anchor",href:"#_1-5-ベクトルの内積と外積","aria-label":'Permalink to "1.5: ベクトルの内積と外積"'},"​")],-1),k=s("ol",{start:"5"},[s("li",null,[s("p",null,[a("ベクトルの内積と外積は分配法則が成立する : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mo",{stretchy:"false"},"("),s("mi",null,"b"),s("mo",null,"+"),s("mi",null,"c"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mo",null,"+"),s("mi",null,"a"),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"a(b+c)=a b+a c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord mathnormal"},"c")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"="),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"x")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"a"),s("mi",null,"y")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"y")]),s("mo",null,"+"),s("mo",null,"⋯"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mo",null,"−"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⊥"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"b")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"a"),s("mi",null,"y")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"z")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"a"),s("mi",null,"z")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"y")]),s("mo",{fence:"true"},")")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"x")]),s("mo",null,"+"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"a"),s("mi",null,"z")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"x")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"z")]),s("mo",{fence:"true"},")")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"y")]),s("mo",null,"+"),s("mo",null,"⋯")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},"]"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"−"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"bold-italic"},"c")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{a} \\cdot \\boldsymbol{b}=\\boldsymbol{b} \\cdot \\boldsymbol{a}=a_x b_x+a_y b_y+\\cdots=a b \\cos \\varphi \\\\ |\\boldsymbol{a} \\times \\boldsymbol{b}|=a b \\sin \\varphi, \\boldsymbol{a} \\times \\boldsymbol{b}=-\\boldsymbol{b} \\times \\boldsymbol{a} \\perp \\boldsymbol{a}, \\boldsymbol{b} \\\\ \\boldsymbol{a} \\times \\boldsymbol{b}=\\left(a_y b_z-a_z b_y\\right) \\boldsymbol{e}_x+\\left(a_z b_x-a_x b_z\\right) \\boldsymbol{e}_y+\\cdots \\\\ \\boldsymbol{a} \\times[\\boldsymbol{b} \\times \\boldsymbol{c}]=(\\boldsymbol{a} \\cdot \\boldsymbol{c}) \\boldsymbol{b}-(\\boldsymbol{a} \\cdot \\boldsymbol{b}) \\boldsymbol{c} \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"6em","vertical-align":"-2.75em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.25em"}},[s("span",{style:{top:"-5.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},"⋯"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])]),s("span",{style:{top:"-3.91em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])])])]),s("span",{style:{top:"-2.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},"⋯")])]),s("span",{style:{top:"-0.91em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.75em"}},[s("span")])])])])])])])])])])]),s("p",null,"スカラー三重積(3 つのベクトルで張られる平行四面 体の体積):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},")"),s("mo",null,"≡"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},"]"),s("mo",null,"="),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{stretchy:"false"},"]"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(\\boldsymbol{a}, \\boldsymbol{b}, \\boldsymbol{c}) \\equiv \\boldsymbol{a} \\cdot[\\boldsymbol{b} \\times \\boldsymbol{c}]=[\\boldsymbol{a} \\times \\boldsymbol{b}] \\cdot \\boldsymbol{c}=(\\boldsymbol{b}, \\boldsymbol{c}, \\boldsymbol{a}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≡"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4445em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mclose"},")")])])])])])])],-1),_=s("h3",{id:"_1-6-余弦定理と正弦定理",tabindex:"-1"},[a("1.6: 余弦定理と正弦定理 "),s("a",{class:"header-anchor",href:"#_1-6-余弦定理と正弦定理","aria-label":'Permalink to "1.6: 余弦定理と正弦定理"'},"​")],-1),M=s("ol",{start:"6"},[s("li",null,[a("余弦定理と正弦定理:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")]),s("mo",null,"="),s("msup",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")]),s("mo",null,"−"),s("mn",null,"2"),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"C")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"a"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"A"),s("mo",null,"="),s("mi",null,"b"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"B"),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"R")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & c^2=a^2+b^2-2 a b \\cos C \\\\ & a / \\sin A=b / \\sin B=2 R \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.7621em"}},[s("span",{class:"pstrut",style:{height:"2.8641em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.2621em"}},[s("span",{class:"pstrut",style:{height:"2.8641em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.8979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),L=s("h3",{id:"_1-7-三角法",tabindex:"-1"},[a("1.7: 三角法 "),s("a",{class:"header-anchor",href:"#_1-7-三角法","aria-label":'Permalink to "1.7: 三角法"'},"​")],-1),P=s("ol",{start:"7"},[s("li",null,[s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"±"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"β")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"∓"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"β")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"∓"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",{stretchy:"false"},")")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mi",null,"α"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mn",null,"2"),s("mi",null,"α")]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("msup",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mi",null,"α"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mn",null,"2"),s("mi",null,"α")]),s("mn",null,"2")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"−"),s("mi",null,"β"),s("mo",{stretchy:"false"},")")]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mo",null,"…")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"="),s("mn",null,"2"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"cos"),s("mo",null,"⁡"),s("mfrac",null,[s("mrow",null,[s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"β")]),s("mn",null,"2")]),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mfrac",null,[s("mrow",null,[s("mi",null,"α"),s("mo",null,"−"),s("mi",null,"β")]),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("mo",null,"…")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\sin (\\alpha \\pm \\beta)=\\sin \\alpha \\cos \\beta \\pm \\cos \\alpha \\sin \\beta \\\\ & \\cos (\\alpha \\pm \\beta)=\\cos \\alpha \\cos \\beta \\mp \\sin \\alpha \\sin \\beta \\\\ & \\tan (\\alpha \\pm \\beta)=(\\tan \\alpha \\pm \\tan \\beta) /(1 \\mp \\tan \\alpha \\tan \\beta) \\\\ & \\cos ^2 \\alpha=\\frac{1+\\cos 2 \\alpha}{2}, \\sin ^2 \\alpha=\\frac{1-\\cos 2 \\alpha}{2} \\\\ & \\cos \\alpha \\cos \\beta=\\frac{\\cos (\\alpha+\\beta)+\\cos (\\alpha-\\beta)}{2}, \\ldots \\\\ & \\cos \\alpha+\\cos \\beta=2\\left(\\cos \\frac{\\alpha+\\beta}{2}+\\cos \\frac{\\alpha-\\beta}{2}\\right), \\ldots \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.9205em","vertical-align":"-5.7102em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.2102em"}},[s("span",{style:{top:"-8.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-7.3202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-5.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-3.8388em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.4258em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"1.0102em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.7102em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.2102em"}},[s("span",{style:{top:"-8.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])]),s("span",{style:{top:"-7.3202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∓"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])]),s("span",{style:{top:"-5.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∓"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-3.8388em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"cos"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"sin"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8719em"}},[s("span",{style:{top:"-3.1208em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-1.4258em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"…")])]),s("span",{style:{top:"1.0102em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"…")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.7102em"}},[s("span")])])])])])])])])])])])])],-1),F=r('

    1.8: 円周角

    1. 円周角は中心角の半分. よって,直角三角形の斜辺は その外接円の直径. もし四角形の対角の和が 180 度な らば,それは円に内接する.

    1.9: 三角形の面樍

    ',3),A=s("ol",{start:"9"},[s("li",null,[a("三角形の面樍 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mi",null,"a"),s("msub",null,[s("mi",null,"h"),s("mi",null,"a")]),s("mo",null,"="),s("mi",null,"p"),s("mi",null,"r"),s("mo",null,"="),s("msqrt",null,[s("mrow",null,[s("mi",null,"p"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"a"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"b"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"c"),s("mo",{stretchy:"false"},")")])]),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"c"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"4"),s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"=\\frac{1}{2} a h_a=p r=\\sqrt{p(p-a)(p-b)(p-c)}=a b c / 4 R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1901em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"h"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"a")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 c340,-704.7,510.7,-1060.3,512,-1067 l0 -0 diff --git a/assets/academic_physics_ipho-formulas-jpn_1.md.fa61cf48.lean.js b/assets/academic_physics_ipho-formulas-jpn_1.md.b1c8984c.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_1.md.fa61cf48.lean.js rename to assets/academic_physics_ipho-formulas-jpn_1.md.b1c8984c.lean.js index 29975733..e0e9006f 100644 --- a/assets/academic_physics_ipho-formulas-jpn_1.md.fa61cf48.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_1.md.b1c8984c.lean.js @@ -1,4 +1,4 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,C as i,o as p,c,H as l,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const as=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 1","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/1.md","filePath":"academic/physics/ipho-formulas-jpn/1.md","lastUpdated":1695377563000}'),h={name:"academic/physics/ipho-formulas-jpn/1.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-1",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 1 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-1","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 1"'},"​")],-1),g=s("h2",{id:"_1-数学",tabindex:"-1"},[a("1: 数学 "),s("a",{class:"header-anchor",href:"#_1-数学","aria-label":'Permalink to "1: 数学"'},"​")],-1),u=s("h3",{id:"_1-1-taylor-展開",tabindex:"-1"},[a("1.1: Taylor 展開 "),s("a",{class:"header-anchor",href:"#_1-1-taylor-展開","aria-label":'Permalink to "1.1: Taylor 展開"'},"​")],-1),y=s("ol",null,[s("li",null,[s("p",null,"Taylor 展開(アバウトに切り捨てる:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"F"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("mo",null,"∑"),s("msup",null,[s("mi",null,"F"),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mo",{stretchy:"false"},")")])]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mi",null,"n")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"F(x)=F\\left(x_{0}\\right)+\\sum F^{(n)}\\left(x_{0}\\right)\\left(x-x_{0}\\right)^{n} / n ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mopen mtight"},"("),s("span",{class:"mord mathnormal mtight"},"n"),s("span",{class:"mclose mtight"},")")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8043em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"n")])])])])]),s("p",null,"線形近似(特別な場合):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"≈"),s("mi",null,"F"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"F"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"F(x) \\approx F\\left(x_{0}\\right)+F^{\\prime}\\left(x_{0}\\right)\\left(x-x_{0}\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0519em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8019em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])]),s("p",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"x"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"≪"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"|x| \\ll 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])]),a(" のときの例 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":")]),s("annotation",{encoding:"application/x-tex"},":")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"x"),s("mo",null,"≈"),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"x"),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"e"),s("mi",null,"x")]),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"\\sin x \\approx x, \\cos x \\approx 1-x^{2} / 2, e^{x} \\approx 1+x ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6679em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6776em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])]),s("span",{class:"mord"},"/2"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x")])])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ln"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"≈"),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"n")]),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"n"),s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"\\ln (1+x) \\approx x,(1+x)^{n} \\approx 1+n x ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"ln"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal"},"x")])])])])])])],-1),d=s("h3",{id:"_1-2-摂動法",tabindex:"-1"},[a("1.2: 摂動法 "),s("a",{class:"header-anchor",href:"#_1-2-摂動法","aria-label":'Permalink to "1.2: 摂動法"'},"​")],-1),v=s("ol",{start:"2"},[s("li",null,[a("摂動法:摂動のない(直接解ける)問題の解を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" 番目の近似値として求め,前の似値に基づく次の近似値の補正を繰り返して解を求める.")])],-1),b=s("h3",{id:"_1-3-定数係数線形微分方程式",tabindex:"-1"},[a("1.3: 定数係数線形微分方程式 "),s("a",{class:"header-anchor",href:"#_1-3-定数係数線形微分方程式","aria-label":'Permalink to "1.3: 定数係数線形微分方程式"'},"​")],-1),x=s("ol",{start:"3"},[s("li",null,[s("p",null,[a("定数係数線形微分方程式 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("msup",null,[s("mi",null,"y"),s("mrow",null,[s("mo",{mathvariant:"normal"},"′"),s("mo",{mathvariant:"normal"},"′")])]),s("mo",null,"+"),s("mi",null,"b"),s("msup",null,[s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"+"),s("mi",null,"c"),s("mi",null,"y"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"a y^{\\prime \\prime}+b y^{\\prime}+c y=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9463em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9463em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"cy"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" の解:")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"="),s("mi",null,"A"),s("mi",null,"exp"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"λ"),s("mn",null,"1")]),s("mi",null,"x"),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("mi",null,"B"),s("mi",null,"exp"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"λ"),s("mn",null,"2")]),s("mi",null,"x"),s("mo",{fence:"true"},")")]),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"y=A \\exp \\left(\\lambda_1 x\\right)+B \\exp \\left(\\lambda_2 x\\right) \\text {. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"exp"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"exp"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])]),s("p",null,[a("ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"λ"),s("mrow",null,[s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2")])])]),s("annotation",{encoding:"application/x-tex"},"\\lambda_{1,2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(" は特性方程式 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("msup",null,[s("mi",null,"λ"),s("mn",null,"2")]),s("mo",null,"+"),s("mi",null,"b"),s("mi",null,"λ"),s("mo",null,"+"),s("mi",null,"c"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"a \\lambda^2+b \\lambda+c=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8974em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"bλ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" の異な る 2 解. もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mo",{separator:"true"},","),s("mi",null,"b"),s("mo",{separator:"true"},","),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"a, b, c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(" が実数で特性方程式の解が複素数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"λ"),s("mrow",null,[s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2")])]),s("mo",null,"="),s("mi",null,"γ"),s("mo",null,"±"),s("mi",null,"i"),s("mi",null,"ω")]),s("annotation",{encoding:"application/x-tex"},"\\lambda_{1,2}=\\gamma \\pm i \\omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω")])])]),a(" ならば,")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"="),s("mi",null,"C"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"γ"),s("mi",null,"x")])]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"ω"),s("mi",null,"x"),s("mo",null,"+"),s("msub",null,[s("mi",null,"φ"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"y=C e^{\\gamma x} \\sin \\left(\\omega x+\\varphi_0\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord mathnormal mtight"},"x")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])])])],-1),z=s("h3",{id:"_1-4-複素数",tabindex:"-1"},[a("1.4: 複素数 "),s("a",{class:"header-anchor",href:"#_1-4-複素数","aria-label":'Permalink to "1.4: 複素数"'},"​")],-1),f=s("ol",{start:"4"},[s("li",null,[s("p",null,"複素数"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"z"),s("mo",null,"="),s("mi",null,"a"),s("mo",null,"+"),s("mi",null,"b"),s("mi",null,"i"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",{separator:"true"},","),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",null,"="),s("mi",null,"a"),s("mo",null,"−"),s("mi",null,"b"),s("mi",null,"i"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("msup",null,[s("mi",{mathvariant:"normal"},"∣"),s("mn",null,"2")]),s("mo",null,"="),s("mi",null,"z"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",null,"="),s("msup",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"φ"),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mfrac",null,[s("mi",null,"b"),s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"Re"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"z"),s("mo",null,"+"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Im"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"z"),s("mo",null,"−"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"i")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",{fence:"true"},"∣")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("mo",{fence:"true"},"∣")]),s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",{fence:"true"},"∣")]),s("mo",{separator:"true"},","),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("mo",null,"+"),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"="),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"+"),s("mi",null,"i"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"+"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"−"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"i")])])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} z=a+b i=|z| e^{i \\varphi}, \\bar{z}=a-b i=|z| e^{-i \\varphi} \\\\ |z|^2=z \\bar{z}=a^2+b^2, \\varphi=\\arg z=\\arcsin \\frac{b}{|z|} \\\\ \\operatorname{Re} z=(z+\\bar{z}) / 2, \\operatorname{Im} z=(z-\\bar{z}) / 2 i \\\\ \\left|z_1 z_2\\right|=\\left|z_1\\right|\\left|z_2\\right|, \\arg z_1 z_2=\\arg z_1+\\arg z_2 \\\\ e^{i \\varphi}=\\cos \\varphi+i \\sin \\varphi \\\\ \\cos \\varphi=\\frac{e^{i \\varphi}+e^{-i \\varphi}}{2}, \\sin \\varphi=\\frac{e^{i \\varphi}-e^{-i \\varphi}}{2 i} \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.1644em","vertical-align":"-5.3322em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8322em"}},[s("span",{style:{top:"-8.4592em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"bi"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"bi"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])]),s("span",{style:{top:"-6.4278em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-4.3518em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"Re")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/2"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"Im")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"i")])]),s("span",{style:{top:"-2.8518em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-1.3171em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])]),s("span",{style:{top:"0.8446em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5017em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5017em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"i")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.3322em"}},[s("span")])])])])])])])])])])])])],-1),w=s("h3",{id:"_1-5-ベクトルの内積と外積",tabindex:"-1"},[a("1.5: ベクトルの内積と外積 "),s("a",{class:"header-anchor",href:"#_1-5-ベクトルの内積と外積","aria-label":'Permalink to "1.5: ベクトルの内積と外積"'},"​")],-1),k=s("ol",{start:"5"},[s("li",null,[s("p",null,[a("ベクトルの内積と外積は分配法則が成立する : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mo",{stretchy:"false"},"("),s("mi",null,"b"),s("mo",null,"+"),s("mi",null,"c"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mo",null,"+"),s("mi",null,"a"),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"a(b+c)=a b+a c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord mathnormal"},"c")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"="),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"x")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"a"),s("mi",null,"y")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"y")]),s("mo",null,"+"),s("mo",null,"⋯"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mo",null,"−"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⊥"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"b")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"a"),s("mi",null,"y")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"z")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"a"),s("mi",null,"z")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"y")]),s("mo",{fence:"true"},")")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"x")]),s("mo",null,"+"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"a"),s("mi",null,"z")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"x")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"z")]),s("mo",{fence:"true"},")")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"y")]),s("mo",null,"+"),s("mo",null,"⋯")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},"]"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"−"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"bold-italic"},"c")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{a} \\cdot \\boldsymbol{b}=\\boldsymbol{b} \\cdot \\boldsymbol{a}=a_x b_x+a_y b_y+\\cdots=a b \\cos \\varphi \\\\ |\\boldsymbol{a} \\times \\boldsymbol{b}|=a b \\sin \\varphi, \\boldsymbol{a} \\times \\boldsymbol{b}=-\\boldsymbol{b} \\times \\boldsymbol{a} \\perp \\boldsymbol{a}, \\boldsymbol{b} \\\\ \\boldsymbol{a} \\times \\boldsymbol{b}=\\left(a_y b_z-a_z b_y\\right) \\boldsymbol{e}_x+\\left(a_z b_x-a_x b_z\\right) \\boldsymbol{e}_y+\\cdots \\\\ \\boldsymbol{a} \\times[\\boldsymbol{b} \\times \\boldsymbol{c}]=(\\boldsymbol{a} \\cdot \\boldsymbol{c}) \\boldsymbol{b}-(\\boldsymbol{a} \\cdot \\boldsymbol{b}) \\boldsymbol{c} \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"6em","vertical-align":"-2.75em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.25em"}},[s("span",{style:{top:"-5.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},"⋯"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])]),s("span",{style:{top:"-3.91em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])])])]),s("span",{style:{top:"-2.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},"⋯")])]),s("span",{style:{top:"-0.91em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.75em"}},[s("span")])])])])])])])])])])]),s("p",null,"スカラー三重積(3 つのベクトルで張られる平行四面 体の体積):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},")"),s("mo",null,"≡"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},"]"),s("mo",null,"="),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{stretchy:"false"},"]"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(\\boldsymbol{a}, \\boldsymbol{b}, \\boldsymbol{c}) \\equiv \\boldsymbol{a} \\cdot[\\boldsymbol{b} \\times \\boldsymbol{c}]=[\\boldsymbol{a} \\times \\boldsymbol{b}] \\cdot \\boldsymbol{c}=(\\boldsymbol{b}, \\boldsymbol{c}, \\boldsymbol{a}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≡"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4445em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mclose"},")")])])])])])])],-1),_=s("h3",{id:"_1-6-余弦定理と正弦定理",tabindex:"-1"},[a("1.6: 余弦定理と正弦定理 "),s("a",{class:"header-anchor",href:"#_1-6-余弦定理と正弦定理","aria-label":'Permalink to "1.6: 余弦定理と正弦定理"'},"​")],-1),M=s("ol",{start:"6"},[s("li",null,[a("余弦定理と正弦定理:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")]),s("mo",null,"="),s("msup",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")]),s("mo",null,"−"),s("mn",null,"2"),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"C")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"a"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"A"),s("mo",null,"="),s("mi",null,"b"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"B"),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"R")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & c^2=a^2+b^2-2 a b \\cos C \\\\ & a / \\sin A=b / \\sin B=2 R \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.7621em"}},[s("span",{class:"pstrut",style:{height:"2.8641em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.2621em"}},[s("span",{class:"pstrut",style:{height:"2.8641em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.8979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),L=s("h3",{id:"_1-7-三角法",tabindex:"-1"},[a("1.7: 三角法 "),s("a",{class:"header-anchor",href:"#_1-7-三角法","aria-label":'Permalink to "1.7: 三角法"'},"​")],-1),P=s("ol",{start:"7"},[s("li",null,[s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"±"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"β")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"∓"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"β")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"∓"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",{stretchy:"false"},")")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mi",null,"α"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mn",null,"2"),s("mi",null,"α")]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("msup",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mi",null,"α"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mn",null,"2"),s("mi",null,"α")]),s("mn",null,"2")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"−"),s("mi",null,"β"),s("mo",{stretchy:"false"},")")]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mo",null,"…")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"="),s("mn",null,"2"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"cos"),s("mo",null,"⁡"),s("mfrac",null,[s("mrow",null,[s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"β")]),s("mn",null,"2")]),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mfrac",null,[s("mrow",null,[s("mi",null,"α"),s("mo",null,"−"),s("mi",null,"β")]),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("mo",null,"…")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\sin (\\alpha \\pm \\beta)=\\sin \\alpha \\cos \\beta \\pm \\cos \\alpha \\sin \\beta \\\\ & \\cos (\\alpha \\pm \\beta)=\\cos \\alpha \\cos \\beta \\mp \\sin \\alpha \\sin \\beta \\\\ & \\tan (\\alpha \\pm \\beta)=(\\tan \\alpha \\pm \\tan \\beta) /(1 \\mp \\tan \\alpha \\tan \\beta) \\\\ & \\cos ^2 \\alpha=\\frac{1+\\cos 2 \\alpha}{2}, \\sin ^2 \\alpha=\\frac{1-\\cos 2 \\alpha}{2} \\\\ & \\cos \\alpha \\cos \\beta=\\frac{\\cos (\\alpha+\\beta)+\\cos (\\alpha-\\beta)}{2}, \\ldots \\\\ & \\cos \\alpha+\\cos \\beta=2\\left(\\cos \\frac{\\alpha+\\beta}{2}+\\cos \\frac{\\alpha-\\beta}{2}\\right), \\ldots \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.9205em","vertical-align":"-5.7102em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.2102em"}},[s("span",{style:{top:"-8.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-7.3202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-5.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-3.8388em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.4258em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"1.0102em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.7102em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.2102em"}},[s("span",{style:{top:"-8.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])]),s("span",{style:{top:"-7.3202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∓"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])]),s("span",{style:{top:"-5.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∓"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-3.8388em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"cos"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"sin"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8719em"}},[s("span",{style:{top:"-3.1208em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-1.4258em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"…")])]),s("span",{style:{top:"1.0102em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"…")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.7102em"}},[s("span")])])])])])])])])])])])])],-1),F=r("",3),A=s("ol",{start:"9"},[s("li",null,[a("三角形の面樍 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mi",null,"a"),s("msub",null,[s("mi",null,"h"),s("mi",null,"a")]),s("mo",null,"="),s("mi",null,"p"),s("mi",null,"r"),s("mo",null,"="),s("msqrt",null,[s("mrow",null,[s("mi",null,"p"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"a"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"b"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"c"),s("mo",{stretchy:"false"},")")])]),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"c"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"4"),s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"=\\frac{1}{2} a h_a=p r=\\sqrt{p(p-a)(p-b)(p-c)}=a b c / 4 R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1901em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"h"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"a")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,C as i,o as p,c,H as l,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const as=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 1","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/1.md","filePath":"academic/physics/ipho-formulas-jpn/1.md","lastUpdated":1699051935000}'),h={name:"academic/physics/ipho-formulas-jpn/1.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-1",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 1 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-1","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 1"'},"​")],-1),g=s("h2",{id:"_1-数学",tabindex:"-1"},[a("1: 数学 "),s("a",{class:"header-anchor",href:"#_1-数学","aria-label":'Permalink to "1: 数学"'},"​")],-1),u=s("h3",{id:"_1-1-taylor-展開",tabindex:"-1"},[a("1.1: Taylor 展開 "),s("a",{class:"header-anchor",href:"#_1-1-taylor-展開","aria-label":'Permalink to "1.1: Taylor 展開"'},"​")],-1),y=s("ol",null,[s("li",null,[s("p",null,"Taylor 展開(アバウトに切り捨てる:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"F"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("mo",null,"∑"),s("msup",null,[s("mi",null,"F"),s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mo",{stretchy:"false"},")")])]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mi",null,"n")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"F(x)=F\\left(x_{0}\\right)+\\sum F^{(n)}\\left(x_{0}\\right)\\left(x-x_{0}\\right)^{n} / n ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mopen mtight"},"("),s("span",{class:"mord mathnormal mtight"},"n"),s("span",{class:"mclose mtight"},")")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8043em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"n")])])])])]),s("p",null,"線形近似(特別な場合):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"≈"),s("mi",null,"F"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"F"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"F(x) \\approx F\\left(x_{0}\\right)+F^{\\prime}\\left(x_{0}\\right)\\left(x-x_{0}\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0519em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8019em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])]),s("p",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"x"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"≪"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"|x| \\ll 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])]),a(" のときの例 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":")]),s("annotation",{encoding:"application/x-tex"},":")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"x"),s("mo",null,"≈"),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"x"),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"e"),s("mi",null,"x")]),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"\\sin x \\approx x, \\cos x \\approx 1-x^{2} / 2, e^{x} \\approx 1+x ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6679em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6776em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])]),s("span",{class:"mord"},"/2"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x")])])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ln"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",null,"≈"),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"n")]),s("mo",null,"≈"),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"n"),s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"\\ln (1+x) \\approx x,(1+x)^{n} \\approx 1+n x ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"ln"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal"},"x")])])])])])])],-1),d=s("h3",{id:"_1-2-摂動法",tabindex:"-1"},[a("1.2: 摂動法 "),s("a",{class:"header-anchor",href:"#_1-2-摂動法","aria-label":'Permalink to "1.2: 摂動法"'},"​")],-1),v=s("ol",{start:"2"},[s("li",null,[a("摂動法:摂動のない(直接解ける)問題の解を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" 番目の近似値として求め,前の似値に基づく次の近似値の補正を繰り返して解を求める.")])],-1),b=s("h3",{id:"_1-3-定数係数線形微分方程式",tabindex:"-1"},[a("1.3: 定数係数線形微分方程式 "),s("a",{class:"header-anchor",href:"#_1-3-定数係数線形微分方程式","aria-label":'Permalink to "1.3: 定数係数線形微分方程式"'},"​")],-1),x=s("ol",{start:"3"},[s("li",null,[s("p",null,[a("定数係数線形微分方程式 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("msup",null,[s("mi",null,"y"),s("mrow",null,[s("mo",{mathvariant:"normal"},"′"),s("mo",{mathvariant:"normal"},"′")])]),s("mo",null,"+"),s("mi",null,"b"),s("msup",null,[s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"+"),s("mi",null,"c"),s("mi",null,"y"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"a y^{\\prime \\prime}+b y^{\\prime}+c y=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9463em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9463em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"cy"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" の解:")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"="),s("mi",null,"A"),s("mi",null,"exp"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"λ"),s("mn",null,"1")]),s("mi",null,"x"),s("mo",{fence:"true"},")")]),s("mo",null,"+"),s("mi",null,"B"),s("mi",null,"exp"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"λ"),s("mn",null,"2")]),s("mi",null,"x"),s("mo",{fence:"true"},")")]),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"y=A \\exp \\left(\\lambda_1 x\\right)+B \\exp \\left(\\lambda_2 x\\right) \\text {. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"exp"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"exp"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])]),s("p",null,[a("ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"λ"),s("mrow",null,[s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2")])])]),s("annotation",{encoding:"application/x-tex"},"\\lambda_{1,2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(" は特性方程式 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("msup",null,[s("mi",null,"λ"),s("mn",null,"2")]),s("mo",null,"+"),s("mi",null,"b"),s("mi",null,"λ"),s("mo",null,"+"),s("mi",null,"c"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"a \\lambda^2+b \\lambda+c=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8974em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"bλ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" の異な る 2 解. もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mo",{separator:"true"},","),s("mi",null,"b"),s("mo",{separator:"true"},","),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"a, b, c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(" が実数で特性方程式の解が複素数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"λ"),s("mrow",null,[s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2")])]),s("mo",null,"="),s("mi",null,"γ"),s("mo",null,"±"),s("mi",null,"i"),s("mi",null,"ω")]),s("annotation",{encoding:"application/x-tex"},"\\lambda_{1,2}=\\gamma \\pm i \\omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mtight"},"2")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω")])])]),a(" ならば,")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"="),s("mi",null,"C"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"γ"),s("mi",null,"x")])]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"ω"),s("mi",null,"x"),s("mo",null,"+"),s("msub",null,[s("mi",null,"φ"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"y=C e^{\\gamma x} \\sin \\left(\\omega x+\\varphi_0\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord mathnormal mtight"},"x")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])])])],-1),z=s("h3",{id:"_1-4-複素数",tabindex:"-1"},[a("1.4: 複素数 "),s("a",{class:"header-anchor",href:"#_1-4-複素数","aria-label":'Permalink to "1.4: 複素数"'},"​")],-1),f=s("ol",{start:"4"},[s("li",null,[s("p",null,"複素数"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"z"),s("mo",null,"="),s("mi",null,"a"),s("mo",null,"+"),s("mi",null,"b"),s("mi",null,"i"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",{separator:"true"},","),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",null,"="),s("mi",null,"a"),s("mo",null,"−"),s("mi",null,"b"),s("mi",null,"i"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("msup",null,[s("mi",{mathvariant:"normal"},"∣"),s("mn",null,"2")]),s("mo",null,"="),s("mi",null,"z"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",null,"="),s("msup",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"φ"),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mfrac",null,[s("mi",null,"b"),s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"z"),s("mi",{mathvariant:"normal"},"∣")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"Re"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"z"),s("mo",null,"+"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Im"),s("mo",null,"⁡"),s("mi",null,"z"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"z"),s("mo",null,"−"),s("mover",{accent:"true"},[s("mi",null,"z"),s("mo",null,"ˉ")]),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"i")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",{fence:"true"},"∣")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("mo",{fence:"true"},"∣")]),s("mrow",null,[s("mo",{fence:"true"},"∣"),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",{fence:"true"},"∣")]),s("mo",{separator:"true"},","),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")]),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"1")]),s("mo",null,"+"),s("mi",null,"arg"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"z"),s("mn",null,"2")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"="),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"+"),s("mi",null,"i"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"+"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"φ")])]),s("mo",null,"−"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"i"),s("mi",null,"φ")])])]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"i")])])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} z=a+b i=|z| e^{i \\varphi}, \\bar{z}=a-b i=|z| e^{-i \\varphi} \\\\ |z|^2=z \\bar{z}=a^2+b^2, \\varphi=\\arg z=\\arcsin \\frac{b}{|z|} \\\\ \\operatorname{Re} z=(z+\\bar{z}) / 2, \\operatorname{Im} z=(z-\\bar{z}) / 2 i \\\\ \\left|z_1 z_2\\right|=\\left|z_1\\right|\\left|z_2\\right|, \\arg z_1 z_2=\\arg z_1+\\arg z_2 \\\\ e^{i \\varphi}=\\cos \\varphi+i \\sin \\varphi \\\\ \\cos \\varphi=\\frac{e^{i \\varphi}+e^{-i \\varphi}}{2}, \\sin \\varphi=\\frac{e^{i \\varphi}-e^{-i \\varphi}}{2 i} \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.1644em","vertical-align":"-5.3322em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.8322em"}},[s("span",{style:{top:"-8.4592em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"bi"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"bi"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])]),s("span",{style:{top:"-6.4278em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord"},"∣")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.936em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-4.3518em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"Re")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/2"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"Im")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5678em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1944em"}},[s("span",{class:"mord"},"ˉ")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"i")])]),s("span",{style:{top:"-2.8518em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},"∣")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.044em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-1.3171em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8747em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])]),s("span",{style:{top:"0.8446em"}},[s("span",{class:"pstrut",style:{height:"3.5017em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5017em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5017em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"i")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mord mathnormal mtight"},"φ")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.3322em"}},[s("span")])])])])])])])])])])])])],-1),w=s("h3",{id:"_1-5-ベクトルの内積と外積",tabindex:"-1"},[a("1.5: ベクトルの内積と外積 "),s("a",{class:"header-anchor",href:"#_1-5-ベクトルの内積と外積","aria-label":'Permalink to "1.5: ベクトルの内積と外積"'},"​")],-1),k=s("ol",{start:"5"},[s("li",null,[s("p",null,[a("ベクトルの内積と外積は分配法則が成立する : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a"),s("mo",{stretchy:"false"},"("),s("mi",null,"b"),s("mo",null,"+"),s("mi",null,"c"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mo",null,"+"),s("mi",null,"a"),s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"a(b+c)=a b+a c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.0833em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord mathnormal"},"c")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"="),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"x")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"a"),s("mi",null,"y")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"y")]),s("mo",null,"+"),s("mo",null,"⋯"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"φ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mo",null,"−"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⊥"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"b")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"a"),s("mi",null,"y")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"z")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"a"),s("mi",null,"z")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"y")]),s("mo",{fence:"true"},")")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"x")]),s("mo",null,"+"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"a"),s("mi",null,"z")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"x")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"b"),s("mi",null,"z")]),s("mo",{fence:"true"},")")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"y")]),s("mo",null,"+"),s("mo",null,"⋯")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},"]"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"−"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"bold-italic"},"c")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{a} \\cdot \\boldsymbol{b}=\\boldsymbol{b} \\cdot \\boldsymbol{a}=a_x b_x+a_y b_y+\\cdots=a b \\cos \\varphi \\\\ |\\boldsymbol{a} \\times \\boldsymbol{b}|=a b \\sin \\varphi, \\boldsymbol{a} \\times \\boldsymbol{b}=-\\boldsymbol{b} \\times \\boldsymbol{a} \\perp \\boldsymbol{a}, \\boldsymbol{b} \\\\ \\boldsymbol{a} \\times \\boldsymbol{b}=\\left(a_y b_z-a_z b_y\\right) \\boldsymbol{e}_x+\\left(a_z b_x-a_x b_z\\right) \\boldsymbol{e}_y+\\cdots \\\\ \\boldsymbol{a} \\times[\\boldsymbol{b} \\times \\boldsymbol{c}]=(\\boldsymbol{a} \\cdot \\boldsymbol{c}) \\boldsymbol{b}-(\\boldsymbol{a} \\cdot \\boldsymbol{b}) \\boldsymbol{c} \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"6em","vertical-align":"-2.75em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.25em"}},[s("span",{style:{top:"-5.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},"⋯"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])]),s("span",{style:{top:"-3.91em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])])])]),s("span",{style:{top:"-2.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},"⋯")])]),s("span",{style:{top:"-0.91em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mclose"},")"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.75em"}},[s("span")])])])])])])])])])])]),s("p",null,"スカラー三重積(3 つのベクトルで張られる平行四面 体の体積):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},")"),s("mo",null,"≡"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"⋅"),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{stretchy:"false"},"]"),s("mo",null,"="),s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{stretchy:"false"},"]"),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"b"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"c"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(\\boldsymbol{a}, \\boldsymbol{b}, \\boldsymbol{c}) \\equiv \\boldsymbol{a} \\cdot[\\boldsymbol{b} \\times \\boldsymbol{c}]=[\\boldsymbol{a} \\times \\boldsymbol{b}] \\cdot \\boldsymbol{c}=(\\boldsymbol{b}, \\boldsymbol{c}, \\boldsymbol{a}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≡"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4445em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mclose"},"]"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"c")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mclose"},")")])])])])])])],-1),_=s("h3",{id:"_1-6-余弦定理と正弦定理",tabindex:"-1"},[a("1.6: 余弦定理と正弦定理 "),s("a",{class:"header-anchor",href:"#_1-6-余弦定理と正弦定理","aria-label":'Permalink to "1.6: 余弦定理と正弦定理"'},"​")],-1),M=s("ol",{start:"6"},[s("li",null,[a("余弦定理と正弦定理:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")]),s("mo",null,"="),s("msup",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")]),s("mo",null,"−"),s("mn",null,"2"),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"C")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"a"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"A"),s("mo",null,"="),s("mi",null,"b"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"B"),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"R")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & c^2=a^2+b^2-2 a b \\cos C \\\\ & a / \\sin A=b / \\sin B=2 R \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.7621em"}},[s("span",{class:"pstrut",style:{height:"2.8641em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.2621em"}},[s("span",{class:"pstrut",style:{height:"2.8641em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.8979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"ab"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),L=s("h3",{id:"_1-7-三角法",tabindex:"-1"},[a("1.7: 三角法 "),s("a",{class:"header-anchor",href:"#_1-7-三角法","aria-label":'Permalink to "1.7: 三角法"'},"​")],-1),P=s("ol",{start:"7"},[s("li",null,[s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"±"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"β")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"∓"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"β")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"±"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"∓"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"tan"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",{stretchy:"false"},")")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mi",null,"α"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mn",null,"2"),s("mi",null,"α")]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("msup",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mi",null,"α"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mn",null,"2"),s("mi",null,"α")]),s("mn",null,"2")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"β"),s("mo",{stretchy:"false"},")"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"α"),s("mo",null,"−"),s("mi",null,"β"),s("mo",{stretchy:"false"},")")]),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mo",null,"…")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β"),s("mo",null,"="),s("mn",null,"2"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"cos"),s("mo",null,"⁡"),s("mfrac",null,[s("mrow",null,[s("mi",null,"α"),s("mo",null,"+"),s("mi",null,"β")]),s("mn",null,"2")]),s("mo",null,"+"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mfrac",null,[s("mrow",null,[s("mi",null,"α"),s("mo",null,"−"),s("mi",null,"β")]),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("mo",null,"…")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\sin (\\alpha \\pm \\beta)=\\sin \\alpha \\cos \\beta \\pm \\cos \\alpha \\sin \\beta \\\\ & \\cos (\\alpha \\pm \\beta)=\\cos \\alpha \\cos \\beta \\mp \\sin \\alpha \\sin \\beta \\\\ & \\tan (\\alpha \\pm \\beta)=(\\tan \\alpha \\pm \\tan \\beta) /(1 \\mp \\tan \\alpha \\tan \\beta) \\\\ & \\cos ^2 \\alpha=\\frac{1+\\cos 2 \\alpha}{2}, \\sin ^2 \\alpha=\\frac{1-\\cos 2 \\alpha}{2} \\\\ & \\cos \\alpha \\cos \\beta=\\frac{\\cos (\\alpha+\\beta)+\\cos (\\alpha-\\beta)}{2}, \\ldots \\\\ & \\cos \\alpha+\\cos \\beta=2\\left(\\cos \\frac{\\alpha+\\beta}{2}+\\cos \\frac{\\alpha-\\beta}{2}\\right), \\ldots \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.9205em","vertical-align":"-5.7102em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.2102em"}},[s("span",{style:{top:"-8.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-7.3202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-5.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-3.8388em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.4258em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"1.0102em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.7102em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.2102em"}},[s("span",{style:{top:"-8.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])]),s("span",{style:{top:"-7.3202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∓"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])]),s("span",{style:{top:"-5.8202em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"±"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∓"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"tan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-3.8388em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"cos"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"sin"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8719em"}},[s("span",{style:{top:"-3.1208em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])]),s("span",{style:{top:"-1.4258em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.427em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mclose"},")")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"…")])]),s("span",{style:{top:"1.0102em"}},[s("span",{class:"pstrut",style:{height:"3.45em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"…")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.7102em"}},[s("span")])])])])])])])])])])])])],-1),F=r("",3),A=s("ol",{start:"9"},[s("li",null,[a("三角形の面樍 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mi",null,"a"),s("msub",null,[s("mi",null,"h"),s("mi",null,"a")]),s("mo",null,"="),s("mi",null,"p"),s("mi",null,"r"),s("mo",null,"="),s("msqrt",null,[s("mrow",null,[s("mi",null,"p"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"a"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"b"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"p"),s("mo",null,"−"),s("mi",null,"c"),s("mo",{stretchy:"false"},")")])]),s("mo",null,"="),s("mi",null,"a"),s("mi",null,"b"),s("mi",null,"c"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"4"),s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"=\\frac{1}{2} a h_a=p r=\\sqrt{p(p-a)(p-b)(p-c)}=a b c / 4 R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1901em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"h"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"a")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 c340,-704.7,510.7,-1060.3,512,-1067 l0 -0 diff --git a/assets/academic_physics_ipho-formulas-jpn_10.md.5252ef94.js b/assets/academic_physics_ipho-formulas-jpn_10.md.2eaa8ad2.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_10.md.5252ef94.js rename to assets/academic_physics_ipho-formulas-jpn_10.md.2eaa8ad2.js index a996c8cb..fbb95f3b 100644 --- a/assets/academic_physics_ipho-formulas-jpn_10.md.5252ef94.js +++ b/assets/academic_physics_ipho-formulas-jpn_10.md.2eaa8ad2.js @@ -1,4 +1,4 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const hs=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 10","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/10.md","filePath":"academic/physics/ipho-formulas-jpn/10.md","lastUpdated":1695377563000}'),r={name:"academic/physics/ipho-formulas-jpn/10.md"},p=s("h1",{id:"formulas-for-ipho-日本語版-section-10",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 10 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-10","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 10"'},"​")],-1),c=s("h2",{id:"_10-熱力学",tabindex:"-1"},[a("10: 熱力学 "),s("a",{class:"header-anchor",href:"#_10-熱力学","aria-label":'Permalink to "10: 熱力学"'},"​")],-1),h=s("h3",{id:"_10-1",tabindex:"-1"},[a("10.1: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mi",null,"V"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"w"),s("mi",null,"M")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"p V=\\frac{w}{M} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02691em"}},"w")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(),s("a",{class:"header-anchor",href:"#_10-1","aria-label":'Permalink to "10.1: $p V=\\frac{w}{M} R T$"'},"​")],-1),o=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mi",null,"V"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"w"),s("mi",null,"M")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"p V=\\frac{w}{M} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02691em"}},"w")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(".")])],-1),g=s("h3",{id:"_10-2-モルの気体の内部エネルギー",tabindex:"-1"},[a("10.2: モルの気体の内部エネルギー "),s("a",{class:"header-anchor",href:"#_10-2-モルの気体の内部エネルギー","aria-label":'Permalink to "10.2: モルの気体の内部エネルギー"'},"​")],-1),u=s("ol",{start:"2"},[s("li",null,[a("1 モルの気体の内部エネルギー: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"i"),s("mn",null,"2")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"U=\\frac{i}{2} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2007em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8557em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(" [訳者注: 単 原子分子理想気体 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"i=3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(", 二原子分子理想気体 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"5"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"i=5]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"5"),s("span",{class:"mclose"},"]")])])]),a(".")])],-1),d=s("h3",{id:"_10-3-標準状態",tabindex:"-1"},[a("10.3: 標準状態 "),s("a",{class:"header-anchor",href:"#_10-3-標準状態","aria-label":'Permalink to "10.3: 標準状態"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("標準状態での 1 モルの気体の体積は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"22.4"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")])]),s("annotation",{encoding:"application/x-tex"},"22.4 \\mathrm{~L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"22.4"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")])])])]),a(".")])],-1),v=s("h3",{id:"_10-4-断熱過程",tabindex:"-1"},[a("10.4: 断熱過程 "),s("a",{class:"header-anchor",href:"#_10-4-断熱過程","aria-label":'Permalink to "10.4: 断熱過程"'},"​")],-1),x=s("ol",{start:"4"},[s("li",null,[a("断熱過程: 音速に比べて遅く, 熱の出入りがない. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("msup",null,[s("mi",null,"V"),s("mi",null,"γ")]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"p V^\\gamma=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(" const. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"T"),s("msup",null,[s("mi",null,"V"),s("mrow",null,[s("mi",null,"γ"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\left(T V^{\\gamma-1}=\\right.")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mbin mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mclose nulldelimiter"})])])])]),a(" const. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])]),a(".")])],-1),b=s("h3",{id:"_10-5-γ-cp-cv-i-2-i",tabindex:"-1"},[a("10.5: γ=Cp/Cv=(i+2)/i "),s("a",{class:"header-anchor",href:"#_10-5-γ-cp-cv-i-2-i","aria-label":'Permalink to "10.5: γ=Cp/Cv=(i+2)/i"'},"​")],-1),w=s("ol",{start:"5"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"γ"),s("mo",null,"="),s("msub",null,[s("mi",null,"c"),s("mi",null,"p")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"c"),s("mi",null,"v")]),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"i"),s("mo",null,"+"),s("mn",null,"2"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"i")]),s("annotation",{encoding:"application/x-tex"},"\\gamma=c_p / c_v=(i+2) / i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0361em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"p")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"v")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"i")])])]),a(".")])],-1),k=s("h3",{id:"_10-6-boltzmann-分布",tabindex:"-1"},[a("10.6: Boltzmann 分布 "),s("a",{class:"header-anchor",href:"#_10-6-boltzmann-分布","aria-label":'Permalink to "10.6: Boltzmann 分布"'},"​")],-1),_=s("ol",{start:"6"},[s("li",null,[a("Boltzmann 分布 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ρ"),s("mo",null,"="),s("msub",null,[s("mi",null,"ρ"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"M"),s("mi",null,"g"),s("mi",null,"h"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R"),s("mi",null,"T")])]),s("mo",null,"="),s("msub",null,[s("mi",null,"ρ"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"U"),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T")])])]),s("annotation",{encoding:"application/x-tex"},"\\rho=\\rho_0 e^{-M g h / R T}=\\rho_0 e^{-U / k_B T} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1324em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord mathnormal mtight"},"h"),s("span",{class:"mord mtight"},"/"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"RT")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1324em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mord mtight"},"/"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.3567em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1433em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"T")])])])])])])])])])])])])])])],-1),z=s("h3",{id:"_10-7-maxwell-分布",tabindex:"-1"},[a("10.7: Maxwell 分布 "),s("a",{class:"header-anchor",href:"#_10-7-maxwell-分布","aria-label":'Permalink to "10.7: Maxwell 分布"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("Maxwell 分布(v の速さをもつ分子の数)"),s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"訳者注"),s("p",null,[a("位相空間で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"v")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}+\\mathrm{d} \\boldsymbol{v}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),a(" の間にある分子の数の分布 であり,v の速さをもつ分子の数の分布とは異なる] "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∝"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"m"),s("msup",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T")])])]),s("annotation",{encoding:"application/x-tex"},"\\propto e^{-m \\boldsymbol{v}^2 / 2 k_B T}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9869em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9869em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"m"),s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord boldsymbol mtight",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-2.931em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord mtight"},"/2"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.3567em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1433em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"T")])])])])])])])])])])])])])])],-1),f=s("h3",{id:"_10-8-大気圧",tabindex:"-1"},[a("10.8: 大気圧 "),s("a",{class:"header-anchor",href:"#_10-8-大気圧","aria-label":'Permalink to "10.8: 大気圧"'},"​")],-1),T=s("ol",{start:"8"},[s("li",null,[a("大気圧 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mo",null,"≪"),s("mi",null,"p")]),s("annotation",{encoding:"application/x-tex"},"\\Delta p \\ll p")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p")])])]),a(" ならば "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mo",null,"="),s("mi",null,"ρ"),s("mi",null,"g"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"\\Delta p=\\rho g \\Delta h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"h")])])]),a(".")])],-1),L=s("h3",{id:"_10-9-公式",tabindex:"-1"},[a("10.9: 公式 "),s("a",{class:"header-anchor",href:"#_10-9-公式","aria-label":'Permalink to "10.9: 公式"'},"​")],-1),P=s("ol",{start:"9"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"3")]),s("mi",null,"m"),s("mi",null,"n"),s("mover",{accent:"true"},[s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",{stretchy:"true"},"‾")]),s("mo",null,"="),s("mi",null,"n"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T"),s("mo",{stretchy:"false"},"("),s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"p=\\frac{1}{3} m n \\overline{v^2}=n k_B T(n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2851em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal"},"mn"),s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.8601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"n")])])]),a(" は数密度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msqrt",null,[s("mover",{accent:"true"},[s("mover",{accent:"true"},[s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",{stretchy:"true"},"‾")]),s("mo",{stretchy:"true"},"‾")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"), \\sqrt{\\overline{\\overline{v^2}}}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.84em","vertical-align":"-0.2849em"}}),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5551em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.8601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])])])]),s("span",{style:{top:"-4.0601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])])])]),s("span",{style:{top:"-3.5151em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const hs=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 10","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/10.md","filePath":"academic/physics/ipho-formulas-jpn/10.md","lastUpdated":1699051935000}'),r={name:"academic/physics/ipho-formulas-jpn/10.md"},p=s("h1",{id:"formulas-for-ipho-日本語版-section-10",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 10 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-10","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 10"'},"​")],-1),c=s("h2",{id:"_10-熱力学",tabindex:"-1"},[a("10: 熱力学 "),s("a",{class:"header-anchor",href:"#_10-熱力学","aria-label":'Permalink to "10: 熱力学"'},"​")],-1),h=s("h3",{id:"_10-1",tabindex:"-1"},[a("10.1: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mi",null,"V"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"w"),s("mi",null,"M")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"p V=\\frac{w}{M} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02691em"}},"w")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(),s("a",{class:"header-anchor",href:"#_10-1","aria-label":'Permalink to "10.1: $p V=\\frac{w}{M} R T$"'},"​")],-1),o=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mi",null,"V"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"w"),s("mi",null,"M")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"p V=\\frac{w}{M} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02691em"}},"w")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(".")])],-1),g=s("h3",{id:"_10-2-モルの気体の内部エネルギー",tabindex:"-1"},[a("10.2: モルの気体の内部エネルギー "),s("a",{class:"header-anchor",href:"#_10-2-モルの気体の内部エネルギー","aria-label":'Permalink to "10.2: モルの気体の内部エネルギー"'},"​")],-1),u=s("ol",{start:"2"},[s("li",null,[a("1 モルの気体の内部エネルギー: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"i"),s("mn",null,"2")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"U=\\frac{i}{2} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2007em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8557em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(" [訳者注: 単 原子分子理想気体 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"i=3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(", 二原子分子理想気体 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"5"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"i=5]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"5"),s("span",{class:"mclose"},"]")])])]),a(".")])],-1),d=s("h3",{id:"_10-3-標準状態",tabindex:"-1"},[a("10.3: 標準状態 "),s("a",{class:"header-anchor",href:"#_10-3-標準状態","aria-label":'Permalink to "10.3: 標準状態"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("標準状態での 1 モルの気体の体積は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"22.4"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")])]),s("annotation",{encoding:"application/x-tex"},"22.4 \\mathrm{~L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"22.4"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")])])])]),a(".")])],-1),v=s("h3",{id:"_10-4-断熱過程",tabindex:"-1"},[a("10.4: 断熱過程 "),s("a",{class:"header-anchor",href:"#_10-4-断熱過程","aria-label":'Permalink to "10.4: 断熱過程"'},"​")],-1),x=s("ol",{start:"4"},[s("li",null,[a("断熱過程: 音速に比べて遅く, 熱の出入りがない. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("msup",null,[s("mi",null,"V"),s("mi",null,"γ")]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"p V^\\gamma=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(" const. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"T"),s("msup",null,[s("mi",null,"V"),s("mrow",null,[s("mi",null,"γ"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\left(T V^{\\gamma-1}=\\right.")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mbin mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mclose nulldelimiter"})])])])]),a(" const. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])]),a(".")])],-1),b=s("h3",{id:"_10-5-γ-cp-cv-i-2-i",tabindex:"-1"},[a("10.5: γ=Cp/Cv=(i+2)/i "),s("a",{class:"header-anchor",href:"#_10-5-γ-cp-cv-i-2-i","aria-label":'Permalink to "10.5: γ=Cp/Cv=(i+2)/i"'},"​")],-1),w=s("ol",{start:"5"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"γ"),s("mo",null,"="),s("msub",null,[s("mi",null,"c"),s("mi",null,"p")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"c"),s("mi",null,"v")]),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"i"),s("mo",null,"+"),s("mn",null,"2"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"i")]),s("annotation",{encoding:"application/x-tex"},"\\gamma=c_p / c_v=(i+2) / i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0361em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"p")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"v")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"i")])])]),a(".")])],-1),k=s("h3",{id:"_10-6-boltzmann-分布",tabindex:"-1"},[a("10.6: Boltzmann 分布 "),s("a",{class:"header-anchor",href:"#_10-6-boltzmann-分布","aria-label":'Permalink to "10.6: Boltzmann 分布"'},"​")],-1),_=s("ol",{start:"6"},[s("li",null,[a("Boltzmann 分布 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ρ"),s("mo",null,"="),s("msub",null,[s("mi",null,"ρ"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"M"),s("mi",null,"g"),s("mi",null,"h"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R"),s("mi",null,"T")])]),s("mo",null,"="),s("msub",null,[s("mi",null,"ρ"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"U"),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T")])])]),s("annotation",{encoding:"application/x-tex"},"\\rho=\\rho_0 e^{-M g h / R T}=\\rho_0 e^{-U / k_B T} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1324em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord mathnormal mtight"},"h"),s("span",{class:"mord mtight"},"/"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"RT")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1324em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mord mtight"},"/"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.3567em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1433em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"T")])])])])])])])])])])])])])])],-1),z=s("h3",{id:"_10-7-maxwell-分布",tabindex:"-1"},[a("10.7: Maxwell 分布 "),s("a",{class:"header-anchor",href:"#_10-7-maxwell-分布","aria-label":'Permalink to "10.7: Maxwell 分布"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("Maxwell 分布(v の速さをもつ分子の数)"),s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"訳者注"),s("p",null,[a("位相空間で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"v")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}+\\mathrm{d} \\boldsymbol{v}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),a(" の間にある分子の数の分布 であり,v の速さをもつ分子の数の分布とは異なる] "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∝"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"m"),s("msup",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T")])])]),s("annotation",{encoding:"application/x-tex"},"\\propto e^{-m \\boldsymbol{v}^2 / 2 k_B T}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9869em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9869em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"m"),s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord boldsymbol mtight",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-2.931em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord mtight"},"/2"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.3567em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1433em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"T")])])])])])])])])])])])])])])],-1),f=s("h3",{id:"_10-8-大気圧",tabindex:"-1"},[a("10.8: 大気圧 "),s("a",{class:"header-anchor",href:"#_10-8-大気圧","aria-label":'Permalink to "10.8: 大気圧"'},"​")],-1),T=s("ol",{start:"8"},[s("li",null,[a("大気圧 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mo",null,"≪"),s("mi",null,"p")]),s("annotation",{encoding:"application/x-tex"},"\\Delta p \\ll p")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p")])])]),a(" ならば "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mo",null,"="),s("mi",null,"ρ"),s("mi",null,"g"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"\\Delta p=\\rho g \\Delta h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"h")])])]),a(".")])],-1),L=s("h3",{id:"_10-9-公式",tabindex:"-1"},[a("10.9: 公式 "),s("a",{class:"header-anchor",href:"#_10-9-公式","aria-label":'Permalink to "10.9: 公式"'},"​")],-1),P=s("ol",{start:"9"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"3")]),s("mi",null,"m"),s("mi",null,"n"),s("mover",{accent:"true"},[s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",{stretchy:"true"},"‾")]),s("mo",null,"="),s("mi",null,"n"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T"),s("mo",{stretchy:"false"},"("),s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"p=\\frac{1}{3} m n \\overline{v^2}=n k_B T(n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2851em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal"},"mn"),s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.8601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"n")])])]),a(" は数密度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msqrt",null,[s("mover",{accent:"true"},[s("mover",{accent:"true"},[s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",{stretchy:"true"},"‾")]),s("mo",{stretchy:"true"},"‾")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"), \\sqrt{\\overline{\\overline{v^2}}}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.84em","vertical-align":"-0.2849em"}}),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5551em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.8601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])])])]),s("span",{style:{top:"-4.0601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])])])]),s("span",{style:{top:"-3.5151em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 l0 -0 c4,-6.7,10,-10,18,-10 H400000v40 H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7 diff --git a/assets/academic_physics_ipho-formulas-jpn_10.md.5252ef94.lean.js b/assets/academic_physics_ipho-formulas-jpn_10.md.2eaa8ad2.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_10.md.5252ef94.lean.js rename to assets/academic_physics_ipho-formulas-jpn_10.md.2eaa8ad2.lean.js index a996c8cb..fbb95f3b 100644 --- a/assets/academic_physics_ipho-formulas-jpn_10.md.5252ef94.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_10.md.2eaa8ad2.lean.js @@ -1,4 +1,4 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const hs=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 10","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/10.md","filePath":"academic/physics/ipho-formulas-jpn/10.md","lastUpdated":1695377563000}'),r={name:"academic/physics/ipho-formulas-jpn/10.md"},p=s("h1",{id:"formulas-for-ipho-日本語版-section-10",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 10 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-10","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 10"'},"​")],-1),c=s("h2",{id:"_10-熱力学",tabindex:"-1"},[a("10: 熱力学 "),s("a",{class:"header-anchor",href:"#_10-熱力学","aria-label":'Permalink to "10: 熱力学"'},"​")],-1),h=s("h3",{id:"_10-1",tabindex:"-1"},[a("10.1: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mi",null,"V"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"w"),s("mi",null,"M")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"p V=\\frac{w}{M} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02691em"}},"w")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(),s("a",{class:"header-anchor",href:"#_10-1","aria-label":'Permalink to "10.1: $p V=\\frac{w}{M} R T$"'},"​")],-1),o=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mi",null,"V"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"w"),s("mi",null,"M")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"p V=\\frac{w}{M} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02691em"}},"w")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(".")])],-1),g=s("h3",{id:"_10-2-モルの気体の内部エネルギー",tabindex:"-1"},[a("10.2: モルの気体の内部エネルギー "),s("a",{class:"header-anchor",href:"#_10-2-モルの気体の内部エネルギー","aria-label":'Permalink to "10.2: モルの気体の内部エネルギー"'},"​")],-1),u=s("ol",{start:"2"},[s("li",null,[a("1 モルの気体の内部エネルギー: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"i"),s("mn",null,"2")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"U=\\frac{i}{2} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2007em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8557em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(" [訳者注: 単 原子分子理想気体 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"i=3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(", 二原子分子理想気体 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"5"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"i=5]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"5"),s("span",{class:"mclose"},"]")])])]),a(".")])],-1),d=s("h3",{id:"_10-3-標準状態",tabindex:"-1"},[a("10.3: 標準状態 "),s("a",{class:"header-anchor",href:"#_10-3-標準状態","aria-label":'Permalink to "10.3: 標準状態"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("標準状態での 1 モルの気体の体積は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"22.4"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")])]),s("annotation",{encoding:"application/x-tex"},"22.4 \\mathrm{~L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"22.4"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")])])])]),a(".")])],-1),v=s("h3",{id:"_10-4-断熱過程",tabindex:"-1"},[a("10.4: 断熱過程 "),s("a",{class:"header-anchor",href:"#_10-4-断熱過程","aria-label":'Permalink to "10.4: 断熱過程"'},"​")],-1),x=s("ol",{start:"4"},[s("li",null,[a("断熱過程: 音速に比べて遅く, 熱の出入りがない. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("msup",null,[s("mi",null,"V"),s("mi",null,"γ")]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"p V^\\gamma=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(" const. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"T"),s("msup",null,[s("mi",null,"V"),s("mrow",null,[s("mi",null,"γ"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\left(T V^{\\gamma-1}=\\right.")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mbin mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mclose nulldelimiter"})])])])]),a(" const. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])]),a(".")])],-1),b=s("h3",{id:"_10-5-γ-cp-cv-i-2-i",tabindex:"-1"},[a("10.5: γ=Cp/Cv=(i+2)/i "),s("a",{class:"header-anchor",href:"#_10-5-γ-cp-cv-i-2-i","aria-label":'Permalink to "10.5: γ=Cp/Cv=(i+2)/i"'},"​")],-1),w=s("ol",{start:"5"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"γ"),s("mo",null,"="),s("msub",null,[s("mi",null,"c"),s("mi",null,"p")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"c"),s("mi",null,"v")]),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"i"),s("mo",null,"+"),s("mn",null,"2"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"i")]),s("annotation",{encoding:"application/x-tex"},"\\gamma=c_p / c_v=(i+2) / i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0361em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"p")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"v")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"i")])])]),a(".")])],-1),k=s("h3",{id:"_10-6-boltzmann-分布",tabindex:"-1"},[a("10.6: Boltzmann 分布 "),s("a",{class:"header-anchor",href:"#_10-6-boltzmann-分布","aria-label":'Permalink to "10.6: Boltzmann 分布"'},"​")],-1),_=s("ol",{start:"6"},[s("li",null,[a("Boltzmann 分布 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ρ"),s("mo",null,"="),s("msub",null,[s("mi",null,"ρ"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"M"),s("mi",null,"g"),s("mi",null,"h"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R"),s("mi",null,"T")])]),s("mo",null,"="),s("msub",null,[s("mi",null,"ρ"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"U"),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T")])])]),s("annotation",{encoding:"application/x-tex"},"\\rho=\\rho_0 e^{-M g h / R T}=\\rho_0 e^{-U / k_B T} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1324em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord mathnormal mtight"},"h"),s("span",{class:"mord mtight"},"/"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"RT")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1324em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mord mtight"},"/"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.3567em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1433em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"T")])])])])])])])])])])])])])])],-1),z=s("h3",{id:"_10-7-maxwell-分布",tabindex:"-1"},[a("10.7: Maxwell 分布 "),s("a",{class:"header-anchor",href:"#_10-7-maxwell-分布","aria-label":'Permalink to "10.7: Maxwell 分布"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("Maxwell 分布(v の速さをもつ分子の数)"),s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"訳者注"),s("p",null,[a("位相空間で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"v")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}+\\mathrm{d} \\boldsymbol{v}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),a(" の間にある分子の数の分布 であり,v の速さをもつ分子の数の分布とは異なる] "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∝"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"m"),s("msup",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T")])])]),s("annotation",{encoding:"application/x-tex"},"\\propto e^{-m \\boldsymbol{v}^2 / 2 k_B T}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9869em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9869em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"m"),s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord boldsymbol mtight",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-2.931em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord mtight"},"/2"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.3567em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1433em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"T")])])])])])])])])])])])])])])],-1),f=s("h3",{id:"_10-8-大気圧",tabindex:"-1"},[a("10.8: 大気圧 "),s("a",{class:"header-anchor",href:"#_10-8-大気圧","aria-label":'Permalink to "10.8: 大気圧"'},"​")],-1),T=s("ol",{start:"8"},[s("li",null,[a("大気圧 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mo",null,"≪"),s("mi",null,"p")]),s("annotation",{encoding:"application/x-tex"},"\\Delta p \\ll p")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p")])])]),a(" ならば "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mo",null,"="),s("mi",null,"ρ"),s("mi",null,"g"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"\\Delta p=\\rho g \\Delta h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"h")])])]),a(".")])],-1),L=s("h3",{id:"_10-9-公式",tabindex:"-1"},[a("10.9: 公式 "),s("a",{class:"header-anchor",href:"#_10-9-公式","aria-label":'Permalink to "10.9: 公式"'},"​")],-1),P=s("ol",{start:"9"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"3")]),s("mi",null,"m"),s("mi",null,"n"),s("mover",{accent:"true"},[s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",{stretchy:"true"},"‾")]),s("mo",null,"="),s("mi",null,"n"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T"),s("mo",{stretchy:"false"},"("),s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"p=\\frac{1}{3} m n \\overline{v^2}=n k_B T(n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2851em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal"},"mn"),s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.8601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"n")])])]),a(" は数密度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msqrt",null,[s("mover",{accent:"true"},[s("mover",{accent:"true"},[s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",{stretchy:"true"},"‾")]),s("mo",{stretchy:"true"},"‾")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"), \\sqrt{\\overline{\\overline{v^2}}}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.84em","vertical-align":"-0.2849em"}}),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5551em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.8601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])])])]),s("span",{style:{top:"-4.0601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])])])]),s("span",{style:{top:"-3.5151em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const hs=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 10","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/10.md","filePath":"academic/physics/ipho-formulas-jpn/10.md","lastUpdated":1699051935000}'),r={name:"academic/physics/ipho-formulas-jpn/10.md"},p=s("h1",{id:"formulas-for-ipho-日本語版-section-10",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 10 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-10","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 10"'},"​")],-1),c=s("h2",{id:"_10-熱力学",tabindex:"-1"},[a("10: 熱力学 "),s("a",{class:"header-anchor",href:"#_10-熱力学","aria-label":'Permalink to "10: 熱力学"'},"​")],-1),h=s("h3",{id:"_10-1",tabindex:"-1"},[a("10.1: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mi",null,"V"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"w"),s("mi",null,"M")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"p V=\\frac{w}{M} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02691em"}},"w")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(),s("a",{class:"header-anchor",href:"#_10-1","aria-label":'Permalink to "10.1: $p V=\\frac{w}{M} R T$"'},"​")],-1),o=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mi",null,"V"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"w"),s("mi",null,"M")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"p V=\\frac{w}{M} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02691em"}},"w")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(".")])],-1),g=s("h3",{id:"_10-2-モルの気体の内部エネルギー",tabindex:"-1"},[a("10.2: モルの気体の内部エネルギー "),s("a",{class:"header-anchor",href:"#_10-2-モルの気体の内部エネルギー","aria-label":'Permalink to "10.2: モルの気体の内部エネルギー"'},"​")],-1),u=s("ol",{start:"2"},[s("li",null,[a("1 モルの気体の内部エネルギー: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"i"),s("mn",null,"2")]),s("mi",null,"R"),s("mi",null,"T")]),s("annotation",{encoding:"application/x-tex"},"U=\\frac{i}{2} R T")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2007em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8557em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"RT")])])]),a(" [訳者注: 単 原子分子理想気体 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"i=3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(", 二原子分子理想気体 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"5"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"i=5]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6595em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"5"),s("span",{class:"mclose"},"]")])])]),a(".")])],-1),d=s("h3",{id:"_10-3-標準状態",tabindex:"-1"},[a("10.3: 標準状態 "),s("a",{class:"header-anchor",href:"#_10-3-標準状態","aria-label":'Permalink to "10.3: 標準状態"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("標準状態での 1 モルの気体の体積は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"22.4"),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"L")])]),s("annotation",{encoding:"application/x-tex"},"22.4 \\mathrm{~L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"22.4"),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"L")])])])]),a(".")])],-1),v=s("h3",{id:"_10-4-断熱過程",tabindex:"-1"},[a("10.4: 断熱過程 "),s("a",{class:"header-anchor",href:"#_10-4-断熱過程","aria-label":'Permalink to "10.4: 断熱過程"'},"​")],-1),x=s("ol",{start:"4"},[s("li",null,[a("断熱過程: 音速に比べて遅く, 熱の出入りがない. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("msup",null,[s("mi",null,"V"),s("mi",null,"γ")]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"p V^\\gamma=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(" const. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"T"),s("msup",null,[s("mi",null,"V"),s("mrow",null,[s("mi",null,"γ"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\left(T V^{\\gamma-1}=\\right.")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mbin mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mclose nulldelimiter"})])])])]),a(" const. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])]),a(".")])],-1),b=s("h3",{id:"_10-5-γ-cp-cv-i-2-i",tabindex:"-1"},[a("10.5: γ=Cp/Cv=(i+2)/i "),s("a",{class:"header-anchor",href:"#_10-5-γ-cp-cv-i-2-i","aria-label":'Permalink to "10.5: γ=Cp/Cv=(i+2)/i"'},"​")],-1),w=s("ol",{start:"5"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"γ"),s("mo",null,"="),s("msub",null,[s("mi",null,"c"),s("mi",null,"p")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"c"),s("mi",null,"v")]),s("mo",null,"="),s("mo",{stretchy:"false"},"("),s("mi",null,"i"),s("mo",null,"+"),s("mn",null,"2"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"i")]),s("annotation",{encoding:"application/x-tex"},"\\gamma=c_p / c_v=(i+2) / i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0361em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"p")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"c"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"v")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"i")])])]),a(".")])],-1),k=s("h3",{id:"_10-6-boltzmann-分布",tabindex:"-1"},[a("10.6: Boltzmann 分布 "),s("a",{class:"header-anchor",href:"#_10-6-boltzmann-分布","aria-label":'Permalink to "10.6: Boltzmann 分布"'},"​")],-1),_=s("ol",{start:"6"},[s("li",null,[a("Boltzmann 分布 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ρ"),s("mo",null,"="),s("msub",null,[s("mi",null,"ρ"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"M"),s("mi",null,"g"),s("mi",null,"h"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R"),s("mi",null,"T")])]),s("mo",null,"="),s("msub",null,[s("mi",null,"ρ"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"U"),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T")])])]),s("annotation",{encoding:"application/x-tex"},"\\rho=\\rho_0 e^{-M g h / R T}=\\rho_0 e^{-U / k_B T} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1324em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord mathnormal mtight"},"h"),s("span",{class:"mord mtight"},"/"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"RT")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1324em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.938em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mord mtight"},"/"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.3567em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1433em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"T")])])])])])])])])])])])])])])],-1),z=s("h3",{id:"_10-7-maxwell-分布",tabindex:"-1"},[a("10.7: Maxwell 分布 "),s("a",{class:"header-anchor",href:"#_10-7-maxwell-分布","aria-label":'Permalink to "10.7: Maxwell 分布"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("Maxwell 分布(v の速さをもつ分子の数)"),s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"訳者注"),s("p",null,[a("位相空間で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"v")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}+\\mathrm{d} \\boldsymbol{v}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),a(" の間にある分子の数の分布 であり,v の速さをもつ分子の数の分布とは異なる] "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∝"),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"m"),s("msup",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T")])])]),s("annotation",{encoding:"application/x-tex"},"\\propto e^{-m \\boldsymbol{v}^2 / 2 k_B T}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9869em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9869em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight"},"m"),s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord boldsymbol mtight",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-2.931em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord mtight"},"/2"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.3567em","margin-left":"-0.0315em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1433em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.13889em"}},"T")])])])])])])])])])])])])])])],-1),f=s("h3",{id:"_10-8-大気圧",tabindex:"-1"},[a("10.8: 大気圧 "),s("a",{class:"header-anchor",href:"#_10-8-大気圧","aria-label":'Permalink to "10.8: 大気圧"'},"​")],-1),T=s("ol",{start:"8"},[s("li",null,[a("大気圧 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mo",null,"≪"),s("mi",null,"p")]),s("annotation",{encoding:"application/x-tex"},"\\Delta p \\ll p")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p")])])]),a(" ならば "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mo",null,"="),s("mi",null,"ρ"),s("mi",null,"g"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"\\Delta p=\\rho g \\Delta h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"h")])])]),a(".")])],-1),L=s("h3",{id:"_10-9-公式",tabindex:"-1"},[a("10.9: 公式 "),s("a",{class:"header-anchor",href:"#_10-9-公式","aria-label":'Permalink to "10.9: 公式"'},"​")],-1),P=s("ol",{start:"9"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"p"),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"3")]),s("mi",null,"m"),s("mi",null,"n"),s("mover",{accent:"true"},[s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",{stretchy:"true"},"‾")]),s("mo",null,"="),s("mi",null,"n"),s("msub",null,[s("mi",null,"k"),s("mi",null,"B")]),s("mi",null,"T"),s("mo",{stretchy:"false"},"("),s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"p=\\frac{1}{3} m n \\overline{v^2}=n k_B T(n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2851em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord mathnormal"},"mn"),s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.8601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"n")])])]),a(" は数密度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msqrt",null,[s("mover",{accent:"true"},[s("mover",{accent:"true"},[s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",{stretchy:"true"},"‾")]),s("mo",{stretchy:"true"},"‾")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"), \\sqrt{\\overline{\\overline{v^2}}}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.84em","vertical-align":"-0.2849em"}}),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5551em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord overline"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9401em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.8601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])])])]),s("span",{style:{top:"-4.0601em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"overline-line",style:{"border-bottom-width":"0.04em"}})])])])])])])]),s("span",{style:{top:"-3.5151em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 l0 -0 c4,-6.7,10,-10,18,-10 H400000v40 H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7 diff --git a/assets/academic_physics_ipho-formulas-jpn_11.md.5f6411f3.js b/assets/academic_physics_ipho-formulas-jpn_11.md.3b777f56.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_11.md.5f6411f3.js rename to assets/academic_physics_ipho-formulas-jpn_11.md.3b777f56.js index 21127ed9..da7d0ed6 100644 --- a/assets/academic_physics_ipho-formulas-jpn_11.md.5f6411f3.js +++ b/assets/academic_physics_ipho-formulas-jpn_11.md.3b777f56.js @@ -1,4 +1,4 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 11","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/11.md","filePath":"academic/physics/ipho-formulas-jpn/11.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/11.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-11",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 11 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-11","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 11"'},"​")],-1),h=s("h2",{id:"_11-量子力学",tabindex:"-1"},[a("11: 量子力学 "),s("a",{class:"header-anchor",href:"#_11-量子力学","aria-label":'Permalink to "11: 量子力学"'},"​")],-1),o=s("h3",{id:"_11-1-p-hk",tabindex:"-1"},[a("11.1:p=hk "),s("a",{class:"header-anchor",href:"#_11-1-p-hk","aria-label":'Permalink to "11.1:p=hk"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"ℏ"),s("mi",{mathvariant:"bold-italic"},"k"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"p"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"="),s("mi",null,"h"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"λ"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"E"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"ℏ"),s("mi",null,"ω"),s("mo",null,"="),s("mi",null,"h"),s("mi",null,"ν")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{p}=\\hbar \\boldsymbol{k}(|\\boldsymbol{p}|=h / \\lambda), E=\\hbar \\omega=h \\nu")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.01852em"}},"k")])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν")])])]),a(".")])],-1),u=r('

    11.2: 干渉

    1. 干渉 : 波動光学のように.

    11.3: 不確定性

    ',3),d=s("ol",{start:"3"},[s("li",null,[s("p",null,"不確定性(数学の定理):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"x"),s("mo",null,"≥"),s("mfrac",null,[s("mi",{mathvariant:"normal"},"ℏ"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t"),s("mo",null,"≥"),s("mfrac",null,[s("mi",{mathvariant:"normal"},"ℏ"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"ω"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t"),s("mo",null,"≥"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\Delta p \\Delta x \\geq \\frac{\\hbar}{2}, \\Delta E \\Delta t \\geq \\frac{\\hbar}{2}, \\Delta \\omega \\Delta t \\geq \\frac{1}{2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0519em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3659em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"ℏ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0519em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3659em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"ℏ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0074em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])]),s("p",null,[a("滑らかでない場合の定性的な推定には "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h")])])]),a(" の方が適する "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"x"),s("mo",null,"≈"),s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"(\\Delta p \\Delta x \\approx h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h")])])]),a(" など "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])]),a(".")])])],-1),y=s("h3",{id:"_11-4-スペクトル",tabindex:"-1"},[a("11.4: スペクトル "),s("a",{class:"header-anchor",href:"#_11-4-スペクトル","aria-label":'Permalink to "11.4: スペクトル"'},"​")],-1),v=s("ol",{start:"4"},[s("li",null,[a("スペクトル : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"h"),s("mi",null,"ν"),s("mo",null,"="),s("msub",null,[s("mi",null,"E"),s("mi",null,"n")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"E"),s("mi",null,"m")])]),s("annotation",{encoding:"application/x-tex"},"h \\nu=E_n-E_m")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"m")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". スペクトル線の幅は寿 命に関係し, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",null,"τ"),s("mo",null,"≈"),s("mi",{mathvariant:"normal"},"ℏ")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma \\tau \\approx \\hbar")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord"},"ℏ")])])]),a(".")])],-1),x=s("h3",{id:"_11-5-振動子",tabindex:"-1"},[a("11.5: 振動子 "),s("a",{class:"header-anchor",href:"#_11-5-振動子","aria-label":'Permalink to "11.5: 振動子"'},"​")],-1),b=s("ol",{start:"5"},[s("li",null,[a("振動子(例えば分子)のエネルギー準位(固有振動数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ν"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,":"),s("msub",null,[s("mi",null,"E"),s("mi",null,"n")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"n"),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",null,"h"),s("msub",null,[s("mi",null,"ν"),s("mn",null,"0")])]),s("annotation",{encoding:"application/x-tex"},"\\left.\\nu_0\\right): E_n=\\left(n+\\frac{1}{2}\\right) h \\nu_0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". 多数の固有振動数の場合, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mo",null,"∑"),s("mi",null,"h"),s("msub",null,[s("mi",null,"n"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"ν"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"E=\\sum h n_i \\nu_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(".")])],-1),w=s("h3",{id:"_11-6-トンネル効果",tabindex:"-1"},[a("11.6: トンネル効果 "),s("a",{class:"header-anchor",href:"#_11-6-トンネル効果","aria-label":'Permalink to "11.6: トンネル効果"'},"​")],-1),_=s("ol",{start:"6"},[s("li",null,[a("トンネル効果: 幅 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(" の障壁 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ")])])]),a(" は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",null,"τ"),s("mo",null,"≈"),s("mi",{mathvariant:"normal"},"ℏ"),s("mo",{stretchy:"false"},"("),s("mi",null,"τ"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma \\tau \\approx \\hbar(\\tau=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"l"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m")])]),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"l / \\sqrt{\\Gamma / m})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mord"},"/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},"Γ/"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 11","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/11.md","filePath":"academic/physics/ipho-formulas-jpn/11.md","lastUpdated":1699051935000}'),p={name:"academic/physics/ipho-formulas-jpn/11.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-11",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 11 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-11","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 11"'},"​")],-1),h=s("h2",{id:"_11-量子力学",tabindex:"-1"},[a("11: 量子力学 "),s("a",{class:"header-anchor",href:"#_11-量子力学","aria-label":'Permalink to "11: 量子力学"'},"​")],-1),o=s("h3",{id:"_11-1-p-hk",tabindex:"-1"},[a("11.1:p=hk "),s("a",{class:"header-anchor",href:"#_11-1-p-hk","aria-label":'Permalink to "11.1:p=hk"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"ℏ"),s("mi",{mathvariant:"bold-italic"},"k"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"p"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"="),s("mi",null,"h"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"λ"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"E"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"ℏ"),s("mi",null,"ω"),s("mo",null,"="),s("mi",null,"h"),s("mi",null,"ν")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{p}=\\hbar \\boldsymbol{k}(|\\boldsymbol{p}|=h / \\lambda), E=\\hbar \\omega=h \\nu")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.01852em"}},"k")])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν")])])]),a(".")])],-1),u=r('

    11.2: 干渉

    1. 干渉 : 波動光学のように.

    11.3: 不確定性

    ',3),d=s("ol",{start:"3"},[s("li",null,[s("p",null,"不確定性(数学の定理):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"x"),s("mo",null,"≥"),s("mfrac",null,[s("mi",{mathvariant:"normal"},"ℏ"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t"),s("mo",null,"≥"),s("mfrac",null,[s("mi",{mathvariant:"normal"},"ℏ"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"ω"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t"),s("mo",null,"≥"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\Delta p \\Delta x \\geq \\frac{\\hbar}{2}, \\Delta E \\Delta t \\geq \\frac{\\hbar}{2}, \\Delta \\omega \\Delta t \\geq \\frac{1}{2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0519em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3659em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"ℏ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0519em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3659em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"ℏ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0074em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])]),s("p",null,[a("滑らかでない場合の定性的な推定には "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h")])])]),a(" の方が適する "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"x"),s("mo",null,"≈"),s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"(\\Delta p \\Delta x \\approx h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h")])])]),a(" など "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])]),a(".")])])],-1),y=s("h3",{id:"_11-4-スペクトル",tabindex:"-1"},[a("11.4: スペクトル "),s("a",{class:"header-anchor",href:"#_11-4-スペクトル","aria-label":'Permalink to "11.4: スペクトル"'},"​")],-1),v=s("ol",{start:"4"},[s("li",null,[a("スペクトル : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"h"),s("mi",null,"ν"),s("mo",null,"="),s("msub",null,[s("mi",null,"E"),s("mi",null,"n")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"E"),s("mi",null,"m")])]),s("annotation",{encoding:"application/x-tex"},"h \\nu=E_n-E_m")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"m")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". スペクトル線の幅は寿 命に関係し, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",null,"τ"),s("mo",null,"≈"),s("mi",{mathvariant:"normal"},"ℏ")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma \\tau \\approx \\hbar")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord"},"ℏ")])])]),a(".")])],-1),x=s("h3",{id:"_11-5-振動子",tabindex:"-1"},[a("11.5: 振動子 "),s("a",{class:"header-anchor",href:"#_11-5-振動子","aria-label":'Permalink to "11.5: 振動子"'},"​")],-1),b=s("ol",{start:"5"},[s("li",null,[a("振動子(例えば分子)のエネルギー準位(固有振動数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ν"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,":"),s("msub",null,[s("mi",null,"E"),s("mi",null,"n")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"n"),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",null,"h"),s("msub",null,[s("mi",null,"ν"),s("mn",null,"0")])]),s("annotation",{encoding:"application/x-tex"},"\\left.\\nu_0\\right): E_n=\\left(n+\\frac{1}{2}\\right) h \\nu_0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". 多数の固有振動数の場合, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mo",null,"∑"),s("mi",null,"h"),s("msub",null,[s("mi",null,"n"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"ν"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"E=\\sum h n_i \\nu_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(".")])],-1),w=s("h3",{id:"_11-6-トンネル効果",tabindex:"-1"},[a("11.6: トンネル効果 "),s("a",{class:"header-anchor",href:"#_11-6-トンネル効果","aria-label":'Permalink to "11.6: トンネル効果"'},"​")],-1),_=s("ol",{start:"6"},[s("li",null,[a("トンネル効果: 幅 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(" の障壁 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ")])])]),a(" は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",null,"τ"),s("mo",null,"≈"),s("mi",{mathvariant:"normal"},"ℏ"),s("mo",{stretchy:"false"},"("),s("mi",null,"τ"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma \\tau \\approx \\hbar(\\tau=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"l"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m")])]),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"l / \\sqrt{\\Gamma / m})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mord"},"/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},"Γ/"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 c340,-704.7,510.7,-1060.3,512,-1067 l0 -0 diff --git a/assets/academic_physics_ipho-formulas-jpn_11.md.5f6411f3.lean.js b/assets/academic_physics_ipho-formulas-jpn_11.md.3b777f56.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_11.md.5f6411f3.lean.js rename to assets/academic_physics_ipho-formulas-jpn_11.md.3b777f56.lean.js index 72955fda..0293532f 100644 --- a/assets/academic_physics_ipho-formulas-jpn_11.md.5f6411f3.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_11.md.3b777f56.lean.js @@ -1,4 +1,4 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 11","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/11.md","filePath":"academic/physics/ipho-formulas-jpn/11.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/11.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-11",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 11 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-11","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 11"'},"​")],-1),h=s("h2",{id:"_11-量子力学",tabindex:"-1"},[a("11: 量子力学 "),s("a",{class:"header-anchor",href:"#_11-量子力学","aria-label":'Permalink to "11: 量子力学"'},"​")],-1),o=s("h3",{id:"_11-1-p-hk",tabindex:"-1"},[a("11.1:p=hk "),s("a",{class:"header-anchor",href:"#_11-1-p-hk","aria-label":'Permalink to "11.1:p=hk"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"ℏ"),s("mi",{mathvariant:"bold-italic"},"k"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"p"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"="),s("mi",null,"h"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"λ"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"E"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"ℏ"),s("mi",null,"ω"),s("mo",null,"="),s("mi",null,"h"),s("mi",null,"ν")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{p}=\\hbar \\boldsymbol{k}(|\\boldsymbol{p}|=h / \\lambda), E=\\hbar \\omega=h \\nu")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.01852em"}},"k")])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν")])])]),a(".")])],-1),u=r("",3),d=s("ol",{start:"3"},[s("li",null,[s("p",null,"不確定性(数学の定理):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"x"),s("mo",null,"≥"),s("mfrac",null,[s("mi",{mathvariant:"normal"},"ℏ"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t"),s("mo",null,"≥"),s("mfrac",null,[s("mi",{mathvariant:"normal"},"ℏ"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"ω"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t"),s("mo",null,"≥"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\Delta p \\Delta x \\geq \\frac{\\hbar}{2}, \\Delta E \\Delta t \\geq \\frac{\\hbar}{2}, \\Delta \\omega \\Delta t \\geq \\frac{1}{2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0519em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3659em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"ℏ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0519em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3659em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"ℏ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0074em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])]),s("p",null,[a("滑らかでない場合の定性的な推定には "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h")])])]),a(" の方が適する "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"x"),s("mo",null,"≈"),s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"(\\Delta p \\Delta x \\approx h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h")])])]),a(" など "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])]),a(".")])])],-1),y=s("h3",{id:"_11-4-スペクトル",tabindex:"-1"},[a("11.4: スペクトル "),s("a",{class:"header-anchor",href:"#_11-4-スペクトル","aria-label":'Permalink to "11.4: スペクトル"'},"​")],-1),v=s("ol",{start:"4"},[s("li",null,[a("スペクトル : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"h"),s("mi",null,"ν"),s("mo",null,"="),s("msub",null,[s("mi",null,"E"),s("mi",null,"n")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"E"),s("mi",null,"m")])]),s("annotation",{encoding:"application/x-tex"},"h \\nu=E_n-E_m")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"m")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". スペクトル線の幅は寿 命に関係し, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",null,"τ"),s("mo",null,"≈"),s("mi",{mathvariant:"normal"},"ℏ")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma \\tau \\approx \\hbar")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord"},"ℏ")])])]),a(".")])],-1),x=s("h3",{id:"_11-5-振動子",tabindex:"-1"},[a("11.5: 振動子 "),s("a",{class:"header-anchor",href:"#_11-5-振動子","aria-label":'Permalink to "11.5: 振動子"'},"​")],-1),b=s("ol",{start:"5"},[s("li",null,[a("振動子(例えば分子)のエネルギー準位(固有振動数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ν"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,":"),s("msub",null,[s("mi",null,"E"),s("mi",null,"n")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"n"),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",null,"h"),s("msub",null,[s("mi",null,"ν"),s("mn",null,"0")])]),s("annotation",{encoding:"application/x-tex"},"\\left.\\nu_0\\right): E_n=\\left(n+\\frac{1}{2}\\right) h \\nu_0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". 多数の固有振動数の場合, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mo",null,"∑"),s("mi",null,"h"),s("msub",null,[s("mi",null,"n"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"ν"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"E=\\sum h n_i \\nu_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(".")])],-1),w=s("h3",{id:"_11-6-トンネル効果",tabindex:"-1"},[a("11.6: トンネル効果 "),s("a",{class:"header-anchor",href:"#_11-6-トンネル効果","aria-label":'Permalink to "11.6: トンネル効果"'},"​")],-1),_=s("ol",{start:"6"},[s("li",null,[a("トンネル効果: 幅 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(" の障壁 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ")])])]),a(" は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",null,"τ"),s("mo",null,"≈"),s("mi",{mathvariant:"normal"},"ℏ"),s("mo",{stretchy:"false"},"("),s("mi",null,"τ"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma \\tau \\approx \\hbar(\\tau=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"l"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m")])]),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"l / \\sqrt{\\Gamma / m})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mord"},"/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},"Γ/"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 11","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/11.md","filePath":"academic/physics/ipho-formulas-jpn/11.md","lastUpdated":1699051935000}'),p={name:"academic/physics/ipho-formulas-jpn/11.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-11",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 11 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-11","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 11"'},"​")],-1),h=s("h2",{id:"_11-量子力学",tabindex:"-1"},[a("11: 量子力学 "),s("a",{class:"header-anchor",href:"#_11-量子力学","aria-label":'Permalink to "11: 量子力学"'},"​")],-1),o=s("h3",{id:"_11-1-p-hk",tabindex:"-1"},[a("11.1:p=hk "),s("a",{class:"header-anchor",href:"#_11-1-p-hk","aria-label":'Permalink to "11.1:p=hk"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"ℏ"),s("mi",{mathvariant:"bold-italic"},"k"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"p"),s("mi",{mathvariant:"normal"},"∣"),s("mo",null,"="),s("mi",null,"h"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"λ"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"E"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"ℏ"),s("mi",null,"ω"),s("mo",null,"="),s("mi",null,"h"),s("mi",null,"ν")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{p}=\\hbar \\boldsymbol{k}(|\\boldsymbol{p}|=h / \\lambda), E=\\hbar \\omega=h \\nu")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.01852em"}},"k")])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν")])])]),a(".")])],-1),u=r("",3),d=s("ol",{start:"3"},[s("li",null,[s("p",null,"不確定性(数学の定理):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"x"),s("mo",null,"≥"),s("mfrac",null,[s("mi",{mathvariant:"normal"},"ℏ"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t"),s("mo",null,"≥"),s("mfrac",null,[s("mi",{mathvariant:"normal"},"ℏ"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"ω"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"t"),s("mo",null,"≥"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\Delta p \\Delta x \\geq \\frac{\\hbar}{2}, \\Delta E \\Delta t \\geq \\frac{\\hbar}{2}, \\Delta \\omega \\Delta t \\geq \\frac{1}{2} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0519em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3659em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"ℏ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0519em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3659em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"ℏ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0074em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])]),s("p",null,[a("滑らかでない場合の定性的な推定には "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h")])])]),a(" の方が適する "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"p"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"x"),s("mo",null,"≈"),s("mi",null,"h")]),s("annotation",{encoding:"application/x-tex"},"(\\Delta p \\Delta x \\approx h")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h")])])]),a(" など "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])]),a(".")])])],-1),y=s("h3",{id:"_11-4-スペクトル",tabindex:"-1"},[a("11.4: スペクトル "),s("a",{class:"header-anchor",href:"#_11-4-スペクトル","aria-label":'Permalink to "11.4: スペクトル"'},"​")],-1),v=s("ol",{start:"4"},[s("li",null,[a("スペクトル : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"h"),s("mi",null,"ν"),s("mo",null,"="),s("msub",null,[s("mi",null,"E"),s("mi",null,"n")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"E"),s("mi",null,"m")])]),s("annotation",{encoding:"application/x-tex"},"h \\nu=E_n-E_m")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"m")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". スペクトル線の幅は寿 命に関係し, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",null,"τ"),s("mo",null,"≈"),s("mi",{mathvariant:"normal"},"ℏ")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma \\tau \\approx \\hbar")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord"},"ℏ")])])]),a(".")])],-1),x=s("h3",{id:"_11-5-振動子",tabindex:"-1"},[a("11.5: 振動子 "),s("a",{class:"header-anchor",href:"#_11-5-振動子","aria-label":'Permalink to "11.5: 振動子"'},"​")],-1),b=s("ol",{start:"5"},[s("li",null,[a("振動子(例えば分子)のエネルギー準位(固有振動数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ν"),s("mn",null,"0")]),s("mo",{fence:"true"},")")]),s("mo",null,":"),s("msub",null,[s("mi",null,"E"),s("mi",null,"n")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"n"),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",null,"h"),s("msub",null,[s("mi",null,"ν"),s("mn",null,"0")])]),s("annotation",{encoding:"application/x-tex"},"\\left.\\nu_0\\right): E_n=\\left(n+\\frac{1}{2}\\right) h \\nu_0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0576em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"n")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". 多数の固有振動数の場合, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mo",null,"∑"),s("mi",null,"h"),s("msub",null,[s("mi",null,"n"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"ν"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"E=\\sum h n_i \\nu_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"h"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.06366em"}},"ν"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0637em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(".")])],-1),w=s("h3",{id:"_11-6-トンネル効果",tabindex:"-1"},[a("11.6: トンネル効果 "),s("a",{class:"header-anchor",href:"#_11-6-トンネル効果","aria-label":'Permalink to "11.6: トンネル効果"'},"​")],-1),_=s("ol",{start:"6"},[s("li",null,[a("トンネル効果: 幅 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(" の障壁 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ")])])]),a(" は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",null,"τ"),s("mo",null,"≈"),s("mi",{mathvariant:"normal"},"ℏ"),s("mo",{stretchy:"false"},"("),s("mi",null,"τ"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\Gamma \\tau \\approx \\hbar(\\tau=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Γ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"ℏ"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"l"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Γ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m")])]),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"l / \\sqrt{\\Gamma / m})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mord"},"/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},"Γ/"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 c340,-704.7,510.7,-1060.3,512,-1067 l0 -0 diff --git a/assets/academic_physics_ipho-formulas-jpn_12.md.b01af32f.js b/assets/academic_physics_ipho-formulas-jpn_12.md.449de813.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_12.md.b01af32f.js rename to assets/academic_physics_ipho-formulas-jpn_12.md.449de813.js index feadfea9..75506ee8 100644 --- a/assets/academic_physics_ipho-formulas-jpn_12.md.b01af32f.js +++ b/assets/academic_physics_ipho-formulas-jpn_12.md.449de813.js @@ -1 +1 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,C as i,o as r,c as p,H as l,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 12","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/12.md","filePath":"academic/physics/ipho-formulas-jpn/12.md","lastUpdated":1695377563000}'),h={name:"academic/physics/ipho-formulas-jpn/12.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-12",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 12 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-12","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 12"'},"​")],-1),g=s("h2",{id:"_12-kepler-の法則",tabindex:"-1"},[a("12: Kepler の法則 "),s("a",{class:"header-anchor",href:"#_12-kepler-の法則","aria-label":'Permalink to "12: Kepler の法則"'},"​")],-1),u=s("h3",{id:"_12-1-f-u",tabindex:"-1"},[a("12.1: F & U "),s("a",{class:"header-anchor",href:"#_12-1-f-u","aria-label":'Permalink to "12.1: F & U"'},"​")],-1),d=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"U"),s("mo",null,"="),s("mo",null,"−"),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"F=G M m / r^2, U=-G M m / r \\text {. }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])],-1),y=c('

    12.2: Kepler の第一法則

    1. Kepler の第一法則 (2 質点の重力相互作用):それぞ れの軌道は,系の質量中心に焦点を持つ楕円,双曲線, 放物線になる. これは Runge-Lenz ベクトルから得ら れる (ポイント 9).

    12.3: Kepler の第二法則

    1. Kepler の第二法則(角運動量の保存): 中心力が働く 場にある質点について,その位置ベクトルは単位時間 に一定の面積を描く.

    12.4: Kepler の第三法則

    ',5),v=s("ol",{start:"4"},[s("li",null,[a("Kepler の第三法則 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msup",null,[s("mi",null,"r"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"2")])])]),s("annotation",{encoding:"application/x-tex"},": r^{-2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a(" に比例する力が働く場で楕円 軌道を描く複数の質点について, 周期は長半径の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mn",null,"3"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\frac{3}{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1901em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(" 乗 に比例する :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msubsup",null,[s("mi",null,"T"),s("mn",null,"1"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msubsup",null,[s("mi",null,"T"),s("mn",null,"2"),s("mn",null,"2")]),s("mo",null,"="),s("msubsup",null,[s("mi",null,"a"),s("mn",null,"1"),s("mn",null,"3")]),s("mi",{mathvariant:"normal"},"/"),s("msubsup",null,[s("mi",null,"a"),s("mn",null,"2"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"T_1^2 / T_2^2=a_1^3 / a_2^3 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])])])])])])])])],-1),b=s("h3",{id:"_12-5-楕円軌道",tabindex:"-1"},[a("12.5: 楕円軌道 "),s("a",{class:"header-anchor",href:"#_12-5-楕円軌道","aria-label":'Permalink to "12.5: 楕円軌道"'},"​")],-1),x=s("ol",{start:"5"},[s("li",null,[a("重力場中で楕円軌道を描く質点の全エネルギー "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"K"),s("mo",null,"+"),s("mi",null,"U"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(K+U)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mclose"},")")])])]),a(" :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mo",null,"−"),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"E=-G M m / 2 a ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"a")])])])])])])],-1),_=s("h3",{id:"_12-6-楕円率",tabindex:"-1"},[a("12.6: 楕円率 "),s("a",{class:"header-anchor",href:"#_12-6-楕円率","aria-label":'Permalink to "12.6: 楕円率"'},"​")],-1),k=s("ol",null,[s("li",null,[a("楕円率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ε"),s("mo",null,"="),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"a"),s("mo",null,"≪"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"\\varepsilon=d / a \\ll 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])]),a(" の場合, 軌道は焦点をずらし た円形をしていると考えられる.")])],-1),w=s("h3",{id:"_12-7-楕円の性質",tabindex:"-1"},[a("12.7: 楕円の性質 "),s("a",{class:"header-anchor",href:"#_12-7-楕円の性質","aria-label":'Permalink to "12.7: 楕円の性質"'},"​")],-1),z=s("ol",{start:"2"},[s("li",null,[a("楕円の性質 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msub",null,[s("mi",null,"l"),s("mn",null,"1")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"l"),s("mn",null,"2")]),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"a"),s("mtext",null,"("),s("msub",null,[s("mi",null,"l"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},": l_1+l_2=2 a ( l_1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord cjk_fallback"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"l"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"l_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は焦点までの距 離). "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"α"),s("mn",null,"1")]),s("mo",null,"="),s("msub",null,[s("mi",null,"α"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\alpha_1=\\alpha_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" (一方の焦点から出た光は他方の焦点に 反射する). "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"S"),s("mo",null,"="),s("mi",null,"π"),s("mi",null,"a"),s("mi",null,"b")]),s("annotation",{encoding:"application/x-tex"},"S=\\pi a b")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"πab")])])]),a(".")])],-1),f=s("h3",{id:"_12-8-円の中心",tabindex:"-1"},[a("12.8: 円の中心 "),s("a",{class:"header-anchor",href:"#_12-8-円の中心","aria-label":'Permalink to "12.8: 円の中心"'},"​")],-1),M=s("ol",{start:"3"},[s("li",null,"円とその円の中心に焦点をもつ楕円は長軸の部分での み接する.")],-1),P={id:"_12-9-nge-lenz-ベクトル",tabindex:"-1"},L=s("a",{class:"header-anchor",href:"#_12-9-nge-lenz-ベクトル","aria-label":'Permalink to "12.9: nge-Lenz ベクトル "'},"​",-1),K=s("ol",{start:"4"},[s("li",null,[a("Runge-Lenz ベクトル(楕円率ベクトル)[訳者注:こ のベクトルはむしろ離心率と関係する.そこでここで は離心率ベクトルとして知られるベクトルを代わりに 記す.これは焦点から近日点に向かう向きで,大きさ が離心率 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"e")]),s("annotation",{encoding:"application/x-tex"},"e")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"e")])])]),a(" に一致する.]:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"M")]),s("mrow",null,[s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m")])]),s("mo",null,"−"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"r")]),s("mo",null,"="),s("mtext",null," const. ")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{e}=\\frac{\\boldsymbol{v} \\times \\boldsymbol{M}}{G M m}-\\boldsymbol{e}_r=\\text { const. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0491em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3631em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const. ")])])])])])])])],-1);function T(G,S,U,F,q,B){const t=e,n=i("Badge");return r(),p("div",null,[o,l(t,{readTime:"1",words:"332"}),g,u,d,y,v,b,x,_,k,w,z,f,M,s("h3",P,[a("12.9: nge-Lenz ベクトル "),l(n,{type:"tip",text:"supplemental"}),a(),L]),K])}const $=m(h,[["render",T]]);export{E as __pageData,$ as default}; +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,C as i,o as r,c as p,H as l,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 12","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/12.md","filePath":"academic/physics/ipho-formulas-jpn/12.md","lastUpdated":1699051935000}'),h={name:"academic/physics/ipho-formulas-jpn/12.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-12",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 12 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-12","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 12"'},"​")],-1),g=s("h2",{id:"_12-kepler-の法則",tabindex:"-1"},[a("12: Kepler の法則 "),s("a",{class:"header-anchor",href:"#_12-kepler-の法則","aria-label":'Permalink to "12: Kepler の法則"'},"​")],-1),u=s("h3",{id:"_12-1-f-u",tabindex:"-1"},[a("12.1: F & U "),s("a",{class:"header-anchor",href:"#_12-1-f-u","aria-label":'Permalink to "12.1: F & U"'},"​")],-1),d=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"U"),s("mo",null,"="),s("mo",null,"−"),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"F=G M m / r^2, U=-G M m / r \\text {. }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])],-1),y=c('

    12.2: Kepler の第一法則

    1. Kepler の第一法則 (2 質点の重力相互作用):それぞ れの軌道は,系の質量中心に焦点を持つ楕円,双曲線, 放物線になる. これは Runge-Lenz ベクトルから得ら れる (ポイント 9).

    12.3: Kepler の第二法則

    1. Kepler の第二法則(角運動量の保存): 中心力が働く 場にある質点について,その位置ベクトルは単位時間 に一定の面積を描く.

    12.4: Kepler の第三法則

    ',5),v=s("ol",{start:"4"},[s("li",null,[a("Kepler の第三法則 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msup",null,[s("mi",null,"r"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"2")])])]),s("annotation",{encoding:"application/x-tex"},": r^{-2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a(" に比例する力が働く場で楕円 軌道を描く複数の質点について, 周期は長半径の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mn",null,"3"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\frac{3}{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1901em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(" 乗 に比例する :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msubsup",null,[s("mi",null,"T"),s("mn",null,"1"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msubsup",null,[s("mi",null,"T"),s("mn",null,"2"),s("mn",null,"2")]),s("mo",null,"="),s("msubsup",null,[s("mi",null,"a"),s("mn",null,"1"),s("mn",null,"3")]),s("mi",{mathvariant:"normal"},"/"),s("msubsup",null,[s("mi",null,"a"),s("mn",null,"2"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"T_1^2 / T_2^2=a_1^3 / a_2^3 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])])])])])])])])],-1),b=s("h3",{id:"_12-5-楕円軌道",tabindex:"-1"},[a("12.5: 楕円軌道 "),s("a",{class:"header-anchor",href:"#_12-5-楕円軌道","aria-label":'Permalink to "12.5: 楕円軌道"'},"​")],-1),x=s("ol",{start:"5"},[s("li",null,[a("重力場中で楕円軌道を描く質点の全エネルギー "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"K"),s("mo",null,"+"),s("mi",null,"U"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(K+U)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mclose"},")")])])]),a(" :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mo",null,"−"),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"E=-G M m / 2 a ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"a")])])])])])])],-1),_=s("h3",{id:"_12-6-楕円率",tabindex:"-1"},[a("12.6: 楕円率 "),s("a",{class:"header-anchor",href:"#_12-6-楕円率","aria-label":'Permalink to "12.6: 楕円率"'},"​")],-1),k=s("ol",null,[s("li",null,[a("楕円率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ε"),s("mo",null,"="),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"a"),s("mo",null,"≪"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"\\varepsilon=d / a \\ll 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])]),a(" の場合, 軌道は焦点をずらし た円形をしていると考えられる.")])],-1),w=s("h3",{id:"_12-7-楕円の性質",tabindex:"-1"},[a("12.7: 楕円の性質 "),s("a",{class:"header-anchor",href:"#_12-7-楕円の性質","aria-label":'Permalink to "12.7: 楕円の性質"'},"​")],-1),z=s("ol",{start:"2"},[s("li",null,[a("楕円の性質 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msub",null,[s("mi",null,"l"),s("mn",null,"1")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"l"),s("mn",null,"2")]),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"a"),s("mtext",null,"("),s("msub",null,[s("mi",null,"l"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},": l_1+l_2=2 a ( l_1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord cjk_fallback"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"l"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"l_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は焦点までの距 離). "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"α"),s("mn",null,"1")]),s("mo",null,"="),s("msub",null,[s("mi",null,"α"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\alpha_1=\\alpha_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" (一方の焦点から出た光は他方の焦点に 反射する). "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"S"),s("mo",null,"="),s("mi",null,"π"),s("mi",null,"a"),s("mi",null,"b")]),s("annotation",{encoding:"application/x-tex"},"S=\\pi a b")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"πab")])])]),a(".")])],-1),f=s("h3",{id:"_12-8-円の中心",tabindex:"-1"},[a("12.8: 円の中心 "),s("a",{class:"header-anchor",href:"#_12-8-円の中心","aria-label":'Permalink to "12.8: 円の中心"'},"​")],-1),M=s("ol",{start:"3"},[s("li",null,"円とその円の中心に焦点をもつ楕円は長軸の部分での み接する.")],-1),P={id:"_12-9-nge-lenz-ベクトル",tabindex:"-1"},L=s("a",{class:"header-anchor",href:"#_12-9-nge-lenz-ベクトル","aria-label":'Permalink to "12.9: nge-Lenz ベクトル "'},"​",-1),K=s("ol",{start:"4"},[s("li",null,[a("Runge-Lenz ベクトル(楕円率ベクトル)[訳者注:こ のベクトルはむしろ離心率と関係する.そこでここで は離心率ベクトルとして知られるベクトルを代わりに 記す.これは焦点から近日点に向かう向きで,大きさ が離心率 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"e")]),s("annotation",{encoding:"application/x-tex"},"e")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"e")])])]),a(" に一致する.]:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"M")]),s("mrow",null,[s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m")])]),s("mo",null,"−"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"r")]),s("mo",null,"="),s("mtext",null," const. ")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{e}=\\frac{\\boldsymbol{v} \\times \\boldsymbol{M}}{G M m}-\\boldsymbol{e}_r=\\text { const. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0491em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3631em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const. ")])])])])])])])],-1);function T(G,S,U,F,q,B){const t=e,n=i("Badge");return r(),p("div",null,[o,l(t,{readTime:"1",words:"332"}),g,u,d,y,v,b,x,_,k,w,z,f,M,s("h3",P,[a("12.9: nge-Lenz ベクトル "),l(n,{type:"tip",text:"supplemental"}),a(),L]),K])}const $=m(h,[["render",T]]);export{E as __pageData,$ as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_12.md.b01af32f.lean.js b/assets/academic_physics_ipho-formulas-jpn_12.md.449de813.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_12.md.b01af32f.lean.js rename to assets/academic_physics_ipho-formulas-jpn_12.md.449de813.lean.js index 5f7410ea..ab1c026f 100644 --- a/assets/academic_physics_ipho-formulas-jpn_12.md.b01af32f.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_12.md.449de813.lean.js @@ -1 +1 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,C as i,o as r,c as p,H as l,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 12","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/12.md","filePath":"academic/physics/ipho-formulas-jpn/12.md","lastUpdated":1695377563000}'),h={name:"academic/physics/ipho-formulas-jpn/12.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-12",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 12 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-12","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 12"'},"​")],-1),g=s("h2",{id:"_12-kepler-の法則",tabindex:"-1"},[a("12: Kepler の法則 "),s("a",{class:"header-anchor",href:"#_12-kepler-の法則","aria-label":'Permalink to "12: Kepler の法則"'},"​")],-1),u=s("h3",{id:"_12-1-f-u",tabindex:"-1"},[a("12.1: F & U "),s("a",{class:"header-anchor",href:"#_12-1-f-u","aria-label":'Permalink to "12.1: F & U"'},"​")],-1),d=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"U"),s("mo",null,"="),s("mo",null,"−"),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"F=G M m / r^2, U=-G M m / r \\text {. }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])],-1),y=c("",5),v=s("ol",{start:"4"},[s("li",null,[a("Kepler の第三法則 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msup",null,[s("mi",null,"r"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"2")])])]),s("annotation",{encoding:"application/x-tex"},": r^{-2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a(" に比例する力が働く場で楕円 軌道を描く複数の質点について, 周期は長半径の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mn",null,"3"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\frac{3}{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1901em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(" 乗 に比例する :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msubsup",null,[s("mi",null,"T"),s("mn",null,"1"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msubsup",null,[s("mi",null,"T"),s("mn",null,"2"),s("mn",null,"2")]),s("mo",null,"="),s("msubsup",null,[s("mi",null,"a"),s("mn",null,"1"),s("mn",null,"3")]),s("mi",{mathvariant:"normal"},"/"),s("msubsup",null,[s("mi",null,"a"),s("mn",null,"2"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"T_1^2 / T_2^2=a_1^3 / a_2^3 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])])])])])])])])],-1),b=s("h3",{id:"_12-5-楕円軌道",tabindex:"-1"},[a("12.5: 楕円軌道 "),s("a",{class:"header-anchor",href:"#_12-5-楕円軌道","aria-label":'Permalink to "12.5: 楕円軌道"'},"​")],-1),x=s("ol",{start:"5"},[s("li",null,[a("重力場中で楕円軌道を描く質点の全エネルギー "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"K"),s("mo",null,"+"),s("mi",null,"U"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(K+U)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mclose"},")")])])]),a(" :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mo",null,"−"),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"E=-G M m / 2 a ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"a")])])])])])])],-1),_=s("h3",{id:"_12-6-楕円率",tabindex:"-1"},[a("12.6: 楕円率 "),s("a",{class:"header-anchor",href:"#_12-6-楕円率","aria-label":'Permalink to "12.6: 楕円率"'},"​")],-1),k=s("ol",null,[s("li",null,[a("楕円率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ε"),s("mo",null,"="),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"a"),s("mo",null,"≪"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"\\varepsilon=d / a \\ll 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])]),a(" の場合, 軌道は焦点をずらし た円形をしていると考えられる.")])],-1),w=s("h3",{id:"_12-7-楕円の性質",tabindex:"-1"},[a("12.7: 楕円の性質 "),s("a",{class:"header-anchor",href:"#_12-7-楕円の性質","aria-label":'Permalink to "12.7: 楕円の性質"'},"​")],-1),z=s("ol",{start:"2"},[s("li",null,[a("楕円の性質 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msub",null,[s("mi",null,"l"),s("mn",null,"1")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"l"),s("mn",null,"2")]),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"a"),s("mtext",null,"("),s("msub",null,[s("mi",null,"l"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},": l_1+l_2=2 a ( l_1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord cjk_fallback"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"l"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"l_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は焦点までの距 離). "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"α"),s("mn",null,"1")]),s("mo",null,"="),s("msub",null,[s("mi",null,"α"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\alpha_1=\\alpha_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" (一方の焦点から出た光は他方の焦点に 反射する). "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"S"),s("mo",null,"="),s("mi",null,"π"),s("mi",null,"a"),s("mi",null,"b")]),s("annotation",{encoding:"application/x-tex"},"S=\\pi a b")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"πab")])])]),a(".")])],-1),f=s("h3",{id:"_12-8-円の中心",tabindex:"-1"},[a("12.8: 円の中心 "),s("a",{class:"header-anchor",href:"#_12-8-円の中心","aria-label":'Permalink to "12.8: 円の中心"'},"​")],-1),M=s("ol",{start:"3"},[s("li",null,"円とその円の中心に焦点をもつ楕円は長軸の部分での み接する.")],-1),P={id:"_12-9-nge-lenz-ベクトル",tabindex:"-1"},L=s("a",{class:"header-anchor",href:"#_12-9-nge-lenz-ベクトル","aria-label":'Permalink to "12.9: nge-Lenz ベクトル "'},"​",-1),K=s("ol",{start:"4"},[s("li",null,[a("Runge-Lenz ベクトル(楕円率ベクトル)[訳者注:こ のベクトルはむしろ離心率と関係する.そこでここで は離心率ベクトルとして知られるベクトルを代わりに 記す.これは焦点から近日点に向かう向きで,大きさ が離心率 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"e")]),s("annotation",{encoding:"application/x-tex"},"e")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"e")])])]),a(" に一致する.]:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"M")]),s("mrow",null,[s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m")])]),s("mo",null,"−"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"r")]),s("mo",null,"="),s("mtext",null," const. ")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{e}=\\frac{\\boldsymbol{v} \\times \\boldsymbol{M}}{G M m}-\\boldsymbol{e}_r=\\text { const. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0491em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3631em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const. ")])])])])])])])],-1);function T(G,S,U,F,q,B){const t=e,n=i("Badge");return r(),p("div",null,[o,l(t,{readTime:"1",words:"332"}),g,u,d,y,v,b,x,_,k,w,z,f,M,s("h3",P,[a("12.9: nge-Lenz ベクトル "),l(n,{type:"tip",text:"supplemental"}),a(),L]),K])}const $=m(h,[["render",T]]);export{E as __pageData,$ as default}; +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,C as i,o as r,c as p,H as l,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 12","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/12.md","filePath":"academic/physics/ipho-formulas-jpn/12.md","lastUpdated":1699051935000}'),h={name:"academic/physics/ipho-formulas-jpn/12.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-12",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 12 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-12","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 12"'},"​")],-1),g=s("h2",{id:"_12-kepler-の法則",tabindex:"-1"},[a("12: Kepler の法則 "),s("a",{class:"header-anchor",href:"#_12-kepler-の法則","aria-label":'Permalink to "12: Kepler の法則"'},"​")],-1),u=s("h3",{id:"_12-1-f-u",tabindex:"-1"},[a("12.1: F & U "),s("a",{class:"header-anchor",href:"#_12-1-f-u","aria-label":'Permalink to "12.1: F & U"'},"​")],-1),d=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"U"),s("mo",null,"="),s("mo",null,"−"),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"F=G M m / r^2, U=-G M m / r \\text {. }")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])],-1),y=c("",5),v=s("ol",{start:"4"},[s("li",null,[a("Kepler の第三法則 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msup",null,[s("mi",null,"r"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"2")])])]),s("annotation",{encoding:"application/x-tex"},": r^{-2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"2")])])])])])])])])])])]),a(" に比例する力が働く場で楕円 軌道を描く複数の質点について, 周期は長半径の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mn",null,"3"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\frac{3}{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1901em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"3")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(" 乗 に比例する :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msubsup",null,[s("mi",null,"T"),s("mn",null,"1"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msubsup",null,[s("mi",null,"T"),s("mn",null,"2"),s("mn",null,"2")]),s("mo",null,"="),s("msubsup",null,[s("mi",null,"a"),s("mn",null,"1"),s("mn",null,"3")]),s("mi",{mathvariant:"normal"},"/"),s("msubsup",null,[s("mi",null,"a"),s("mn",null,"2"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"T_1^2 / T_2^2=a_1^3 / a_2^3 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"T"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])])])])])])])])],-1),b=s("h3",{id:"_12-5-楕円軌道",tabindex:"-1"},[a("12.5: 楕円軌道 "),s("a",{class:"header-anchor",href:"#_12-5-楕円軌道","aria-label":'Permalink to "12.5: 楕円軌道"'},"​")],-1),x=s("ol",{start:"5"},[s("li",null,[a("重力場中で楕円軌道を描く質点の全エネルギー "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"K"),s("mo",null,"+"),s("mi",null,"U"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(K+U)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mclose"},")")])])]),a(" :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mo",null,"−"),s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m"),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"E=-G M m / 2 a ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"a")])])])])])])],-1),_=s("h3",{id:"_12-6-楕円率",tabindex:"-1"},[a("12.6: 楕円率 "),s("a",{class:"header-anchor",href:"#_12-6-楕円率","aria-label":'Permalink to "12.6: 楕円率"'},"​")],-1),k=s("ol",null,[s("li",null,[a("楕円率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ε"),s("mo",null,"="),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"a"),s("mo",null,"≪"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"\\varepsilon=d / a \\ll 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])]),a(" の場合, 軌道は焦点をずらし た円形をしていると考えられる.")])],-1),w=s("h3",{id:"_12-7-楕円の性質",tabindex:"-1"},[a("12.7: 楕円の性質 "),s("a",{class:"header-anchor",href:"#_12-7-楕円の性質","aria-label":'Permalink to "12.7: 楕円の性質"'},"​")],-1),z=s("ol",{start:"2"},[s("li",null,[a("楕円の性質 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msub",null,[s("mi",null,"l"),s("mn",null,"1")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"l"),s("mn",null,"2")]),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"a"),s("mtext",null,"("),s("msub",null,[s("mi",null,"l"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},": l_1+l_2=2 a ( l_1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord cjk_fallback"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"l"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"l_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8444em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0197em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は焦点までの距 離). "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"α"),s("mn",null,"1")]),s("mo",null,"="),s("msub",null,[s("mi",null,"α"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\alpha_1=\\alpha_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" (一方の焦点から出た光は他方の焦点に 反射する). "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"S"),s("mo",null,"="),s("mi",null,"π"),s("mi",null,"a"),s("mi",null,"b")]),s("annotation",{encoding:"application/x-tex"},"S=\\pi a b")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"πab")])])]),a(".")])],-1),f=s("h3",{id:"_12-8-円の中心",tabindex:"-1"},[a("12.8: 円の中心 "),s("a",{class:"header-anchor",href:"#_12-8-円の中心","aria-label":'Permalink to "12.8: 円の中心"'},"​")],-1),M=s("ol",{start:"3"},[s("li",null,"円とその円の中心に焦点をもつ楕円は長軸の部分での み接する.")],-1),P={id:"_12-9-nge-lenz-ベクトル",tabindex:"-1"},L=s("a",{class:"header-anchor",href:"#_12-9-nge-lenz-ベクトル","aria-label":'Permalink to "12.9: nge-Lenz ベクトル "'},"​",-1),K=s("ol",{start:"4"},[s("li",null,[a("Runge-Lenz ベクトル(楕円率ベクトル)[訳者注:こ のベクトルはむしろ離心率と関係する.そこでここで は離心率ベクトルとして知られるベクトルを代わりに 記す.これは焦点から近日点に向かう向きで,大きさ が離心率 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"e")]),s("annotation",{encoding:"application/x-tex"},"e")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"e")])])]),a(" に一致する.]:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"M")]),s("mrow",null,[s("mi",null,"G"),s("mi",null,"M"),s("mi",null,"m")])]),s("mo",null,"−"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"r")]),s("mo",null,"="),s("mtext",null," const. ")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{e}=\\frac{\\boldsymbol{v} \\times \\boldsymbol{M}}{G M m}-\\boldsymbol{e}_r=\\text { const. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0491em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3631em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const. ")])])])])])])])],-1);function T(G,S,U,F,q,B){const t=e,n=i("Badge");return r(),p("div",null,[o,l(t,{readTime:"1",words:"332"}),g,u,d,y,v,b,x,_,k,w,z,f,M,s("h3",P,[a("12.9: nge-Lenz ベクトル "),l(n,{type:"tip",text:"supplemental"}),a(),L]),K])}const $=m(h,[["render",T]]);export{E as __pageData,$ as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_13.md.5d106b26.js b/assets/academic_physics_ipho-formulas-jpn_13.md.20d2560f.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_13.md.5d106b26.js rename to assets/academic_physics_ipho-formulas-jpn_13.md.20d2560f.js index 7276dab0..43848bb2 100644 --- a/assets/academic_physics_ipho-formulas-jpn_13.md.5d106b26.js +++ b/assets/academic_physics_ipho-formulas-jpn_13.md.20d2560f.js @@ -1,4 +1,4 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,C as i,o as p,c as r,H as l,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const J=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 13","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/13.md","filePath":"academic/physics/ipho-formulas-jpn/13.md","lastUpdated":1695377563000}'),c={name:"academic/physics/ipho-formulas-jpn/13.md"},h=s("h1",{id:"formulas-for-ipho-日本語版-section-13",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 13 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-13","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 13"'},"​")],-1),o=s("h2",{id:"_13-相対性理論",tabindex:"-1"},[a("13: 相対性理論 "),s("a",{class:"header-anchor",href:"#_13-相対性理論","aria-label":'Permalink to "13: 相対性理論"'},"​")],-1),g=s("h3",{id:"_13-1-lorentz-変換",tabindex:"-1"},[a("13.1:Lorentz 変換 "),s("a",{class:"header-anchor",href:"#_13-1-lorentz-変換","aria-label":'Permalink to "13.1:Lorentz 変換"'},"​")],-1),u=s("ol",null,[s("li",null,[s("p",null,[a("Lorentz 変換 (Minkowski 幾何学の 4 次元時空の回 転)(慣性系間の速度が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"V"),s("mo",null,"="),s("mi",null,"V"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"x")]),s("mo",{fence:"true"},")")]),s("mo",null,":"),s("mi",null,"β"),s("mo",null,"="),s("mi",null,"V"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",{separator:"true"},","),s("mi",null,"γ"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\left.\\boldsymbol{V}=V \\boldsymbol{e}_x\\right): \\beta=V / c, \\gamma=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.25555em"}},"V")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"β"),s("mn",null,"2")])])]),s("mtext",null," として, ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mspace",{width:"2em"}),s("mi",null,"c"),s("msup",null,[s("mi",null,"t"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mo",{stretchy:"false"},"("),s("mi",null,"c"),s("mi",null,"t"),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"x"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"c"),s("mi",null,"t"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"y")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"E"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",null,"="),s("mi",null,"γ"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",null,"−"),s("mi",null,"β"),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"p"),s("mi",null,"x"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"p"),s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("msub",null,[s("mi",null,"p"),s("mi",null,"y")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mtext",null," ここで, ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"m"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])]),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])])])]),s("mo",null,"="),s("mi",null,"m"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")]),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mi",null,"m"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",null,"+"),s("mo",null,"⋯")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"m"),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")])]),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])])])]),s("mo",{separator:"true"},","),s("mtext",null," etc. ")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & 1 / \\sqrt{1-\\beta^2} \\text { として, } \\\\ & \\qquad c t^{\\prime}=\\gamma(c t-\\beta x), x^{\\prime}=\\gamma(x-\\beta c t), y^{\\prime}=y \\\\ & E^{\\prime} / c=\\gamma\\left(E / c-\\beta p_x\\right), p_x^{\\prime}=\\gamma\\left(p_x-\\beta E / c\\right), p_y^{\\prime}=p_y \\\\ & \\text { ここで, } \\\\ & E=\\frac{m c^2}{\\sqrt{1-v^2 / c^2}}=m c^2+\\frac{1}{2} m v^2+\\cdots \\\\ & p_x=\\frac{m v_x}{\\sqrt{1-v^2 / c^2}}, \\text { etc. } \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.6485em","vertical-align":"-5.5742em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.0742em"}},[s("span",{style:{top:"-8.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-7.0586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-5.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.0355em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.8844em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"0.6531em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.5742em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.0742em"}},[s("span",{style:{top:"-8.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},"1/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.0067em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-2.9667em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,C as i,o as p,c as r,H as l,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const J=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 13","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/13.md","filePath":"academic/physics/ipho-formulas-jpn/13.md","lastUpdated":1699051935000}'),c={name:"academic/physics/ipho-formulas-jpn/13.md"},h=s("h1",{id:"formulas-for-ipho-日本語版-section-13",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 13 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-13","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 13"'},"​")],-1),o=s("h2",{id:"_13-相対性理論",tabindex:"-1"},[a("13: 相対性理論 "),s("a",{class:"header-anchor",href:"#_13-相対性理論","aria-label":'Permalink to "13: 相対性理論"'},"​")],-1),g=s("h3",{id:"_13-1-lorentz-変換",tabindex:"-1"},[a("13.1:Lorentz 変換 "),s("a",{class:"header-anchor",href:"#_13-1-lorentz-変換","aria-label":'Permalink to "13.1:Lorentz 変換"'},"​")],-1),u=s("ol",null,[s("li",null,[s("p",null,[a("Lorentz 変換 (Minkowski 幾何学の 4 次元時空の回 転)(慣性系間の速度が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"V"),s("mo",null,"="),s("mi",null,"V"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"x")]),s("mo",{fence:"true"},")")]),s("mo",null,":"),s("mi",null,"β"),s("mo",null,"="),s("mi",null,"V"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",{separator:"true"},","),s("mi",null,"γ"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\left.\\boldsymbol{V}=V \\boldsymbol{e}_x\\right): \\beta=V / c, \\gamma=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.25555em"}},"V")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"β"),s("mn",null,"2")])])]),s("mtext",null," として, ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mspace",{width:"2em"}),s("mi",null,"c"),s("msup",null,[s("mi",null,"t"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mo",{stretchy:"false"},"("),s("mi",null,"c"),s("mi",null,"t"),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"x"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"c"),s("mi",null,"t"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"y")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"E"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",null,"="),s("mi",null,"γ"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",null,"−"),s("mi",null,"β"),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"p"),s("mi",null,"x"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"p"),s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("msub",null,[s("mi",null,"p"),s("mi",null,"y")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mtext",null," ここで, ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"m"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])]),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])])])]),s("mo",null,"="),s("mi",null,"m"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")]),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mi",null,"m"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",null,"+"),s("mo",null,"⋯")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"m"),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")])]),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])])])]),s("mo",{separator:"true"},","),s("mtext",null," etc. ")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & 1 / \\sqrt{1-\\beta^2} \\text { として, } \\\\ & \\qquad c t^{\\prime}=\\gamma(c t-\\beta x), x^{\\prime}=\\gamma(x-\\beta c t), y^{\\prime}=y \\\\ & E^{\\prime} / c=\\gamma\\left(E / c-\\beta p_x\\right), p_x^{\\prime}=\\gamma\\left(p_x-\\beta E / c\\right), p_y^{\\prime}=p_y \\\\ & \\text { ここで, } \\\\ & E=\\frac{m c^2}{\\sqrt{1-v^2 / c^2}}=m c^2+\\frac{1}{2} m v^2+\\cdots \\\\ & p_x=\\frac{m v_x}{\\sqrt{1-v^2 / c^2}}, \\text { etc. } \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.6485em","vertical-align":"-5.5742em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.0742em"}},[s("span",{style:{top:"-8.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-7.0586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-5.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.0355em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.8844em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"0.6531em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.5742em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.0742em"}},[s("span",{style:{top:"-8.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},"1/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.0067em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-2.9667em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 c340,-704.7,510.7,-1060.3,512,-1067 l0 -0 diff --git a/assets/academic_physics_ipho-formulas-jpn_13.md.5d106b26.lean.js b/assets/academic_physics_ipho-formulas-jpn_13.md.20d2560f.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_13.md.5d106b26.lean.js rename to assets/academic_physics_ipho-formulas-jpn_13.md.20d2560f.lean.js index 7276dab0..43848bb2 100644 --- a/assets/academic_physics_ipho-formulas-jpn_13.md.5d106b26.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_13.md.20d2560f.lean.js @@ -1,4 +1,4 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,C as i,o as p,c as r,H as l,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const J=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 13","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/13.md","filePath":"academic/physics/ipho-formulas-jpn/13.md","lastUpdated":1695377563000}'),c={name:"academic/physics/ipho-formulas-jpn/13.md"},h=s("h1",{id:"formulas-for-ipho-日本語版-section-13",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 13 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-13","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 13"'},"​")],-1),o=s("h2",{id:"_13-相対性理論",tabindex:"-1"},[a("13: 相対性理論 "),s("a",{class:"header-anchor",href:"#_13-相対性理論","aria-label":'Permalink to "13: 相対性理論"'},"​")],-1),g=s("h3",{id:"_13-1-lorentz-変換",tabindex:"-1"},[a("13.1:Lorentz 変換 "),s("a",{class:"header-anchor",href:"#_13-1-lorentz-変換","aria-label":'Permalink to "13.1:Lorentz 変換"'},"​")],-1),u=s("ol",null,[s("li",null,[s("p",null,[a("Lorentz 変換 (Minkowski 幾何学の 4 次元時空の回 転)(慣性系間の速度が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"V"),s("mo",null,"="),s("mi",null,"V"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"x")]),s("mo",{fence:"true"},")")]),s("mo",null,":"),s("mi",null,"β"),s("mo",null,"="),s("mi",null,"V"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",{separator:"true"},","),s("mi",null,"γ"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\left.\\boldsymbol{V}=V \\boldsymbol{e}_x\\right): \\beta=V / c, \\gamma=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.25555em"}},"V")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"β"),s("mn",null,"2")])])]),s("mtext",null," として, ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mspace",{width:"2em"}),s("mi",null,"c"),s("msup",null,[s("mi",null,"t"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mo",{stretchy:"false"},"("),s("mi",null,"c"),s("mi",null,"t"),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"x"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"c"),s("mi",null,"t"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"y")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"E"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",null,"="),s("mi",null,"γ"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",null,"−"),s("mi",null,"β"),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"p"),s("mi",null,"x"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"p"),s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("msub",null,[s("mi",null,"p"),s("mi",null,"y")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mtext",null," ここで, ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"m"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])]),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])])])]),s("mo",null,"="),s("mi",null,"m"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")]),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mi",null,"m"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",null,"+"),s("mo",null,"⋯")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"m"),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")])]),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])])])]),s("mo",{separator:"true"},","),s("mtext",null," etc. ")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & 1 / \\sqrt{1-\\beta^2} \\text { として, } \\\\ & \\qquad c t^{\\prime}=\\gamma(c t-\\beta x), x^{\\prime}=\\gamma(x-\\beta c t), y^{\\prime}=y \\\\ & E^{\\prime} / c=\\gamma\\left(E / c-\\beta p_x\\right), p_x^{\\prime}=\\gamma\\left(p_x-\\beta E / c\\right), p_y^{\\prime}=p_y \\\\ & \\text { ここで, } \\\\ & E=\\frac{m c^2}{\\sqrt{1-v^2 / c^2}}=m c^2+\\frac{1}{2} m v^2+\\cdots \\\\ & p_x=\\frac{m v_x}{\\sqrt{1-v^2 / c^2}}, \\text { etc. } \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.6485em","vertical-align":"-5.5742em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.0742em"}},[s("span",{style:{top:"-8.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-7.0586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-5.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.0355em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.8844em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"0.6531em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.5742em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.0742em"}},[s("span",{style:{top:"-8.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},"1/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.0067em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-2.9667em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,C as i,o as p,c as r,H as l,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const J=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 13","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/13.md","filePath":"academic/physics/ipho-formulas-jpn/13.md","lastUpdated":1699051935000}'),c={name:"academic/physics/ipho-formulas-jpn/13.md"},h=s("h1",{id:"formulas-for-ipho-日本語版-section-13",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 13 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-13","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 13"'},"​")],-1),o=s("h2",{id:"_13-相対性理論",tabindex:"-1"},[a("13: 相対性理論 "),s("a",{class:"header-anchor",href:"#_13-相対性理論","aria-label":'Permalink to "13: 相対性理論"'},"​")],-1),g=s("h3",{id:"_13-1-lorentz-変換",tabindex:"-1"},[a("13.1:Lorentz 変換 "),s("a",{class:"header-anchor",href:"#_13-1-lorentz-変換","aria-label":'Permalink to "13.1:Lorentz 変換"'},"​")],-1),u=s("ol",null,[s("li",null,[s("p",null,[a("Lorentz 変換 (Minkowski 幾何学の 4 次元時空の回 転)(慣性系間の速度が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"V"),s("mo",null,"="),s("mi",null,"V"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"x")]),s("mo",{fence:"true"},")")]),s("mo",null,":"),s("mi",null,"β"),s("mo",null,"="),s("mi",null,"V"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",{separator:"true"},","),s("mi",null,"γ"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\left.\\boldsymbol{V}=V \\boldsymbol{e}_x\\right): \\beta=V / c, \\gamma=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.25555em"}},"V")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"c"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"β"),s("mn",null,"2")])])]),s("mtext",null," として, ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mspace",{width:"2em"}),s("mi",null,"c"),s("msup",null,[s("mi",null,"t"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mo",{stretchy:"false"},"("),s("mi",null,"c"),s("mi",null,"t"),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"x"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"x"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"c"),s("mi",null,"t"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("msup",null,[s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"y")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"E"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",null,"="),s("mi",null,"γ"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",null,"−"),s("mi",null,"β"),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"p"),s("mi",null,"x"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"γ"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",null,"−"),s("mi",null,"β"),s("mi",null,"E"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"c"),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"p"),s("mi",null,"y"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("msub",null,[s("mi",null,"p"),s("mi",null,"y")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mtext",null," ここで, ")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"m"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])]),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])])])]),s("mo",null,"="),s("mi",null,"m"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")]),s("mo",null,"+"),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mi",null,"m"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",null,"+"),s("mo",null,"⋯")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"m"),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")])]),s("msqrt",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"−"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"c"),s("mn",null,"2")])])])]),s("mo",{separator:"true"},","),s("mtext",null," etc. ")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & 1 / \\sqrt{1-\\beta^2} \\text { として, } \\\\ & \\qquad c t^{\\prime}=\\gamma(c t-\\beta x), x^{\\prime}=\\gamma(x-\\beta c t), y^{\\prime}=y \\\\ & E^{\\prime} / c=\\gamma\\left(E / c-\\beta p_x\\right), p_x^{\\prime}=\\gamma\\left(p_x-\\beta E / c\\right), p_y^{\\prime}=p_y \\\\ & \\text { ここで, } \\\\ & E=\\frac{m c^2}{\\sqrt{1-v^2 / c^2}}=m c^2+\\frac{1}{2} m v^2+\\cdots \\\\ & p_x=\\frac{m v_x}{\\sqrt{1-v^2 / c^2}}, \\text { etc. } \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"11.6485em","vertical-align":"-5.5742em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.0742em"}},[s("span",{style:{top:"-8.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-7.0586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-5.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.0355em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.8844em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"0.6531em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"5.5742em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"6.0742em"}},[s("span",{style:{top:"-8.5586em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},"1/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.0067em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-2.9667em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 c340,-704.7,510.7,-1060.3,512,-1067 l0 -0 diff --git a/assets/academic_physics_ipho-formulas-jpn_2.md.f9a6af54.js b/assets/academic_physics_ipho-formulas-jpn_2.md.6d273404.js similarity index 97% rename from assets/academic_physics_ipho-formulas-jpn_2.md.f9a6af54.js rename to assets/academic_physics_ipho-formulas-jpn_2.md.6d273404.js index 5eed662c..e2378f2a 100644 --- a/assets/academic_physics_ipho-formulas-jpn_2.md.f9a6af54.js +++ b/assets/academic_physics_ipho-formulas-jpn_2.md.6d273404.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as l,H as i,k as a,a as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const g=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 2","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/2.md","filePath":"academic/physics/ipho-formulas-jpn/2.md","lastUpdated":1695377563000}'),r={name:"academic/physics/ipho-formulas-jpn/2.md"},c=a("h1",{id:"formulas-for-ipho-日本語版-section-2",tabindex:"-1"},[e("Formulas for IPhO 日本語版: Section 2 "),a("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-2","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 2"'},"​")],-1),m=a("h2",{id:"_2-一般的な推奨事",tabindex:"-1"},[e("2: 一般的な推奨事 "),a("a",{class:"header-anchor",href:"#_2-一般的な推奨事","aria-label":'Permalink to "2: 一般的な推奨事"'},"​")],-1),h=a("ol",null,[a("li",null,[e("全ての計算式の正しさを確かめる:a) 次元を調べる. b) 簡単で特別な場合を調べる(2 つの変数が等しい, 1 つの変数が 0 または "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"∞")]),a("annotation",{encoding:"application/x-tex"},"\\infty")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.4306em"}}),a("span",{class:"mord"},"∞")])])]),e(" ). c) 解の定性的な挙動の妥当 性を調ベる. 2.もし問題文中に驚くベき偶然の一致があれば(例えば 2 つのものが同じ), 解答の鍵はそこにあるかもしれ ない.")]),a("li",null,"問題文中の推奨事項をよく読む. 些細な部分に重要な 情報が含まれている場合があるので,問題文の文言に 注意する. かなり時間をかけても問題が解けない場合 は, 問題を誤解しているかもしれないので, もう一度 問題文を読む."),a("li",null,"長くて時間のかかる計算は, 簡略化しなければならな い始めの方程式を全て書き出したのち, 最後(他の全 てが終わったとき) まで先送りする."),a("li",null,"絶望的に難しいと思われる問題でも,たいてい非常に シンプルな解法がある.オリンピックの問題に限って 言えば,絶対に解ける."),a("li",null,"実験では, a) 測定するほどの時問が無いとしても, 実 験計画の概略を書く,b) 結果の正確さを高める方法を 考える,c) 測定した值を全て(表として)書き出す.")],-1);function p(d,_,f,u,x,k){const s=t;return n(),l("div",null,[c,i(s,{readTime:"1",words:"210"}),m,h])}const y=o(r,[["render",p]]);export{g as __pageData,y as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as l,H as i,k as a,a as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const g=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 2","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/2.md","filePath":"academic/physics/ipho-formulas-jpn/2.md","lastUpdated":1699051935000}'),r={name:"academic/physics/ipho-formulas-jpn/2.md"},c=a("h1",{id:"formulas-for-ipho-日本語版-section-2",tabindex:"-1"},[e("Formulas for IPhO 日本語版: Section 2 "),a("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-2","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 2"'},"​")],-1),m=a("h2",{id:"_2-一般的な推奨事",tabindex:"-1"},[e("2: 一般的な推奨事 "),a("a",{class:"header-anchor",href:"#_2-一般的な推奨事","aria-label":'Permalink to "2: 一般的な推奨事"'},"​")],-1),h=a("ol",null,[a("li",null,[e("全ての計算式の正しさを確かめる:a) 次元を調べる. b) 簡単で特別な場合を調べる(2 つの変数が等しい, 1 つの変数が 0 または "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"∞")]),a("annotation",{encoding:"application/x-tex"},"\\infty")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.4306em"}}),a("span",{class:"mord"},"∞")])])]),e(" ). c) 解の定性的な挙動の妥当 性を調ベる. 2.もし問題文中に驚くベき偶然の一致があれば(例えば 2 つのものが同じ), 解答の鍵はそこにあるかもしれ ない.")]),a("li",null,"問題文中の推奨事項をよく読む. 些細な部分に重要な 情報が含まれている場合があるので,問題文の文言に 注意する. かなり時間をかけても問題が解けない場合 は, 問題を誤解しているかもしれないので, もう一度 問題文を読む."),a("li",null,"長くて時間のかかる計算は, 簡略化しなければならな い始めの方程式を全て書き出したのち, 最後(他の全 てが終わったとき) まで先送りする."),a("li",null,"絶望的に難しいと思われる問題でも,たいてい非常に シンプルな解法がある.オリンピックの問題に限って 言えば,絶対に解ける."),a("li",null,"実験では, a) 測定するほどの時問が無いとしても, 実 験計画の概略を書く,b) 結果の正確さを高める方法を 考える,c) 測定した值を全て(表として)書き出す.")],-1);function p(d,_,f,u,x,k){const s=t;return n(),l("div",null,[c,i(s,{readTime:"1",words:"210"}),m,h])}const y=o(r,[["render",p]]);export{g as __pageData,y as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_2.md.f9a6af54.lean.js b/assets/academic_physics_ipho-formulas-jpn_2.md.6d273404.lean.js similarity index 97% rename from assets/academic_physics_ipho-formulas-jpn_2.md.f9a6af54.lean.js rename to assets/academic_physics_ipho-formulas-jpn_2.md.6d273404.lean.js index 5eed662c..e2378f2a 100644 --- a/assets/academic_physics_ipho-formulas-jpn_2.md.f9a6af54.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_2.md.6d273404.lean.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as l,H as i,k as a,a as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const g=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 2","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/2.md","filePath":"academic/physics/ipho-formulas-jpn/2.md","lastUpdated":1695377563000}'),r={name:"academic/physics/ipho-formulas-jpn/2.md"},c=a("h1",{id:"formulas-for-ipho-日本語版-section-2",tabindex:"-1"},[e("Formulas for IPhO 日本語版: Section 2 "),a("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-2","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 2"'},"​")],-1),m=a("h2",{id:"_2-一般的な推奨事",tabindex:"-1"},[e("2: 一般的な推奨事 "),a("a",{class:"header-anchor",href:"#_2-一般的な推奨事","aria-label":'Permalink to "2: 一般的な推奨事"'},"​")],-1),h=a("ol",null,[a("li",null,[e("全ての計算式の正しさを確かめる:a) 次元を調べる. b) 簡単で特別な場合を調べる(2 つの変数が等しい, 1 つの変数が 0 または "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"∞")]),a("annotation",{encoding:"application/x-tex"},"\\infty")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.4306em"}}),a("span",{class:"mord"},"∞")])])]),e(" ). c) 解の定性的な挙動の妥当 性を調ベる. 2.もし問題文中に驚くベき偶然の一致があれば(例えば 2 つのものが同じ), 解答の鍵はそこにあるかもしれ ない.")]),a("li",null,"問題文中の推奨事項をよく読む. 些細な部分に重要な 情報が含まれている場合があるので,問題文の文言に 注意する. かなり時間をかけても問題が解けない場合 は, 問題を誤解しているかもしれないので, もう一度 問題文を読む."),a("li",null,"長くて時間のかかる計算は, 簡略化しなければならな い始めの方程式を全て書き出したのち, 最後(他の全 てが終わったとき) まで先送りする."),a("li",null,"絶望的に難しいと思われる問題でも,たいてい非常に シンプルな解法がある.オリンピックの問題に限って 言えば,絶対に解ける."),a("li",null,"実験では, a) 測定するほどの時問が無いとしても, 実 験計画の概略を書く,b) 結果の正確さを高める方法を 考える,c) 測定した值を全て(表として)書き出す.")],-1);function p(d,_,f,u,x,k){const s=t;return n(),l("div",null,[c,i(s,{readTime:"1",words:"210"}),m,h])}const y=o(r,[["render",p]]);export{g as __pageData,y as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as l,H as i,k as a,a as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const g=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 2","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/2.md","filePath":"academic/physics/ipho-formulas-jpn/2.md","lastUpdated":1699051935000}'),r={name:"academic/physics/ipho-formulas-jpn/2.md"},c=a("h1",{id:"formulas-for-ipho-日本語版-section-2",tabindex:"-1"},[e("Formulas for IPhO 日本語版: Section 2 "),a("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-2","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 2"'},"​")],-1),m=a("h2",{id:"_2-一般的な推奨事",tabindex:"-1"},[e("2: 一般的な推奨事 "),a("a",{class:"header-anchor",href:"#_2-一般的な推奨事","aria-label":'Permalink to "2: 一般的な推奨事"'},"​")],-1),h=a("ol",null,[a("li",null,[e("全ての計算式の正しさを確かめる:a) 次元を調べる. b) 簡単で特別な場合を調べる(2 つの変数が等しい, 1 つの変数が 0 または "),a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("semantics",null,[a("mrow",null,[a("mi",{mathvariant:"normal"},"∞")]),a("annotation",{encoding:"application/x-tex"},"\\infty")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.4306em"}}),a("span",{class:"mord"},"∞")])])]),e(" ). c) 解の定性的な挙動の妥当 性を調ベる. 2.もし問題文中に驚くベき偶然の一致があれば(例えば 2 つのものが同じ), 解答の鍵はそこにあるかもしれ ない.")]),a("li",null,"問題文中の推奨事項をよく読む. 些細な部分に重要な 情報が含まれている場合があるので,問題文の文言に 注意する. かなり時間をかけても問題が解けない場合 は, 問題を誤解しているかもしれないので, もう一度 問題文を読む."),a("li",null,"長くて時間のかかる計算は, 簡略化しなければならな い始めの方程式を全て書き出したのち, 最後(他の全 てが終わったとき) まで先送りする."),a("li",null,"絶望的に難しいと思われる問題でも,たいてい非常に シンプルな解法がある.オリンピックの問題に限って 言えば,絶対に解ける."),a("li",null,"実験では, a) 測定するほどの時問が無いとしても, 実 験計画の概略を書く,b) 結果の正確さを高める方法を 考える,c) 測定した值を全て(表として)書き出す.")],-1);function p(d,_,f,u,x,k){const s=t;return n(),l("div",null,[c,i(s,{readTime:"1",words:"210"}),m,h])}const y=o(r,[["render",p]]);export{g as __pageData,y as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_3.md.aadd6536.js b/assets/academic_physics_ipho-formulas-jpn_3.md.6485844d.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_3.md.aadd6536.js rename to assets/academic_physics_ipho-formulas-jpn_3.md.6485844d.js index ecac32e6..d6461a7c 100644 --- a/assets/academic_physics_ipho-formulas-jpn_3.md.aadd6536.js +++ b/assets/academic_physics_ipho-formulas-jpn_3.md.6485844d.js @@ -1 +1 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as l,k as s,a,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const V=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 3","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/3.md","filePath":"academic/physics/ipho-formulas-jpn/3.md","lastUpdated":1695377563000}'),o={name:"academic/physics/ipho-formulas-jpn/3.md"},h=s("h1",{id:"formulas-for-ipho-日本語版-section-3",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 3 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-3","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 3"'},"​")],-1),g=s("h2",{id:"_3-運動学",tabindex:"-1"},[a("3: 運動学 "),s("a",{class:"header-anchor",href:"#_3-運動学","aria-label":'Permalink to "3: 運動学"'},"​")],-1),d=s("h3",{id:"_3-1-質点",tabindex:"-1"},[a("3.1: 質点 "),s("a",{class:"header-anchor",href:"#_3-1-質点","aria-label":'Permalink to "3.1: 質点"'},"​")],-1),u=s("ol",null,[s("li",null,[a("質点または剛体の並進運動の場合(積分 → グラフの下 の面積):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"x")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"x"),s("mo",null,"="),s("mo",null,"∫"),s("mi",{mathvariant:"bold-italic"},"v"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"t"),s("mtext",null," など "),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"v")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"d"),s("mn",null,"2")]),s("mi",{mathvariant:"bold-italic"},"x")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("msup",null,[s("mi",null,"t"),s("mn",null,"2")])])]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"="),s("mo",null,"∫"),s("mi",{mathvariant:"bold-italic"},"a"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"t"),s("mo",null,"="),s("mo",null,"∫"),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"x"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("msubsup",null,[s("mi",null,"a"),s("mi",null,"x"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("mfrac",null,[s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{v}=\\frac{\\mathrm{d} \\boldsymbol{x}}{\\mathrm{d} t}, \\boldsymbol{x}=\\int \\boldsymbol{v} \\mathrm{d} t\\left(x=\\int v_x \\mathrm{~d} t \\text { など }\\right) \\\\ \\boldsymbol{a}=\\frac{\\mathrm{d} \\boldsymbol{v}}{\\mathrm{d} t}=\\frac{\\mathrm{d}^2 \\boldsymbol{x}}{\\mathrm{d} t^2}, \\boldsymbol{v}=\\int \\boldsymbol{a} \\mathrm{d} t \\\\ t=\\int v_x^{-1} \\mathrm{~d} x=\\int a_x^{-1} \\mathrm{~d} v_x, x=\\int \\frac{v_x}{a_x} \\mathrm{~d} v_x \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"7.8756em","vertical-align":"-3.6878em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1878em"}},[s("span",{style:{top:"-6.2289em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"など"),s("span",{class:"mord"}," ")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])])])]),s("span",{style:{top:"-3.4878em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.4911em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-0.9655em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1076em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.836em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6878em"}},[s("span")])])])])])])])])])])]),a(" もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(" が定数ならば, これらの積分は簡単に求めるこ とができて, 例えば"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mn",null,"0")]),s("mi",null,"t"),s("mo",null,"+"),s("mi",null,"a"),s("msup",null,[s("mi",null,"t"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",null,"−"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"a"),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"x=v_0 t+a t^2 / 2=\\left(v^2-v_0^2\\right) / 2 a \\text {. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7651em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/2"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2141em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])])])],-1),y=s("h3",{id:"_3-2-回転運動",tabindex:"-1"},[a("3.2: 回転運動 "),s("a",{class:"header-anchor",href:"#_3-2-回転運動","aria-label":'Permalink to "3.2: 回転運動"'},"​")],-1),v=s("ol",{start:"2"},[s("li",null,[a("回転運動は, 並進運動と似ていて:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",null,"ω")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",{separator:"true"},","),s("mi",null,"ε"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"ω"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",{mathvariant:"bold-italic"},"a")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"τ"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"v"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",null,"+"),s("mi",{mathvariant:"bold-italic"},"n"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} \\omega & =\\mathrm{d} \\varphi / \\mathrm{d} t, \\varepsilon=\\mathrm{d} \\omega / \\mathrm{d} t \\\\ \\boldsymbol{a} & =\\boldsymbol{\\tau} \\mathrm{d} v / \\mathrm{d} t+\\boldsymbol{n} v^2 / R \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.9221em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.9221em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.13472em"}},"τ")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"n")])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),b=t('

    3.3: 曲線運動

    1. 曲線運動は,ポイント 1 と同じだが,ベクトルは線速 度,加速度,経路長に置き換える.

    3.4: 剛体の運動

    ',3),x=s("ol",{start:"4"},[s("li",null,[a("剛体の運動: "),s("ul",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"v"),s("mi",null,"A")]),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mi",null,"B")]),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β")]),s("annotation",{encoding:"application/x-tex"},"v_A \\cos \\alpha=v_B \\cos \\beta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),a(" ここで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は剛体上の点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A")]),s("annotation",{encoding:"application/x-tex"},"A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" の速度, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"α")]),s("annotation",{encoding:"application/x-tex"},"\\alpha")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"β")]),s("annotation",{encoding:"application/x-tex"},"\\beta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),a(" は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" が直線 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" となす角.")]),s("li",null,[a("瞬間回転中心 (#質点の軌道 の曲率中心)は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{a}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"b")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{b}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])])])])]),a(" に下ろした垂線の交点. 又は もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")]),s("mo",null,"⊥"),s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A, \\boldsymbol{v}_B \\perp A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" ならば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" の先端を結ぶ 直線と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" の交点.")])])])],-1),w=s("h3",{id:"_3-5-非慣性系",tabindex:"-1"},[a("3.5: 非慣性系 "),s("a",{class:"header-anchor",href:"#_3-5-非慣性系","aria-label":'Permalink to "3.5: 非慣性系"'},"​")],-1),z=s("ol",{start:"5"},[s("li",null,[a("非慣性系:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.16em",columnalign:"right",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mspace",{width:"1em"}),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"0")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"0")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"1")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"ω"),s("mn",null,"2")]),s("mi",{mathvariant:"bold-italic"},"R"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mtext",null," ここで, "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])]),s("mo",null,"⊥"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"."),s("mtext",null," もし "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mo",null,"="),s("mn",null,"0"),s("mtext",null," なら "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])]),s("mo",null,"="),s("mn",null,"0.")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{array}{r} \\quad \\boldsymbol{v}_2=\\boldsymbol{v}_0+\\boldsymbol{v}_1, \\boldsymbol{a}_2=\\boldsymbol{a}_0+\\boldsymbol{a}_1+\\omega^2 \\boldsymbol{R}+\\boldsymbol{a}_{C o r} \\\\ \\text { ここで, } \\boldsymbol{a}_{C o r} \\perp \\boldsymbol{v}_1 . \\text { もし } \\boldsymbol{v}_1=0 \\text { なら } \\boldsymbol{a}_{C o r}=0 . \\end{array} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"arraycolsep",style:{width:"0.5em"}}),s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.45em"}},[s("span",{style:{top:"-3.61em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.00421em"}},"R")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-2.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"ここで"),s("span",{class:"mord"},", ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"."),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"もし"),s("span",{class:"mord"}," ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"なら"),s("span",{class:"mord"}," ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.95em"}},[s("span")])])])]),s("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])])])])],-1),_={id:"_3-6-弾道問題",tabindex:"-1"},k=s("a",{class:"header-anchor",href:"#_3-6-弾道問題","aria-label":'Permalink to "3.6: 弾道問題 "'},"​",-1),f=s("ol",{start:"6"},[s("li",null,[a("弾道問題:到達可能な範囲は"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"≤"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mn",null,"2"),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"−"),s("mi",null,"g"),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"2"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"y \\leq v_0^2 /(2 g)-g x^2 /\\left(2 v_0^2\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8304em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≤"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2141em","vertical-align":"-0.35em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])])])])])])]),a(" 最適な弾道では, 初速度と終速(衝突時の速度)が垂直 になる.")])],-1),M=t('

    3.7: 最短経路

    1. 最短経路を求めるには,Fermat と Huygens の原理が 使える.

    3.8: ベクトル

    1. ベクトル(速度,加速度)を求めるには,その向きと (場合によっては傾いた)ある軸への射影を求めれば 充分.
    ',4);function A(B,L,P,C,T,S){const n=e,m=p("Badge");return r(),c("div",null,[h,l(n,{readTime:"2",words:"473"}),g,d,u,y,v,b,x,w,z,s("h3",_,[a("3.6: 弾道問題 "),l(m,{type:"tip",text:"supplemental"}),a(),k]),f,M])}const j=i(o,[["render",A]]);export{V as __pageData,j as default}; +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as l,k as s,a,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const V=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 3","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/3.md","filePath":"academic/physics/ipho-formulas-jpn/3.md","lastUpdated":1699051935000}'),o={name:"academic/physics/ipho-formulas-jpn/3.md"},h=s("h1",{id:"formulas-for-ipho-日本語版-section-3",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 3 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-3","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 3"'},"​")],-1),g=s("h2",{id:"_3-運動学",tabindex:"-1"},[a("3: 運動学 "),s("a",{class:"header-anchor",href:"#_3-運動学","aria-label":'Permalink to "3: 運動学"'},"​")],-1),d=s("h3",{id:"_3-1-質点",tabindex:"-1"},[a("3.1: 質点 "),s("a",{class:"header-anchor",href:"#_3-1-質点","aria-label":'Permalink to "3.1: 質点"'},"​")],-1),u=s("ol",null,[s("li",null,[a("質点または剛体の並進運動の場合(積分 → グラフの下 の面積):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"x")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"x"),s("mo",null,"="),s("mo",null,"∫"),s("mi",{mathvariant:"bold-italic"},"v"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"t"),s("mtext",null," など "),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"v")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"d"),s("mn",null,"2")]),s("mi",{mathvariant:"bold-italic"},"x")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("msup",null,[s("mi",null,"t"),s("mn",null,"2")])])]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"="),s("mo",null,"∫"),s("mi",{mathvariant:"bold-italic"},"a"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"t"),s("mo",null,"="),s("mo",null,"∫"),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"x"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("msubsup",null,[s("mi",null,"a"),s("mi",null,"x"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("mfrac",null,[s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{v}=\\frac{\\mathrm{d} \\boldsymbol{x}}{\\mathrm{d} t}, \\boldsymbol{x}=\\int \\boldsymbol{v} \\mathrm{d} t\\left(x=\\int v_x \\mathrm{~d} t \\text { など }\\right) \\\\ \\boldsymbol{a}=\\frac{\\mathrm{d} \\boldsymbol{v}}{\\mathrm{d} t}=\\frac{\\mathrm{d}^2 \\boldsymbol{x}}{\\mathrm{d} t^2}, \\boldsymbol{v}=\\int \\boldsymbol{a} \\mathrm{d} t \\\\ t=\\int v_x^{-1} \\mathrm{~d} x=\\int a_x^{-1} \\mathrm{~d} v_x, x=\\int \\frac{v_x}{a_x} \\mathrm{~d} v_x \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"7.8756em","vertical-align":"-3.6878em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1878em"}},[s("span",{style:{top:"-6.2289em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"など"),s("span",{class:"mord"}," ")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])])])]),s("span",{style:{top:"-3.4878em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.4911em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-0.9655em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1076em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.836em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6878em"}},[s("span")])])])])])])])])])])]),a(" もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(" が定数ならば, これらの積分は簡単に求めるこ とができて, 例えば"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mn",null,"0")]),s("mi",null,"t"),s("mo",null,"+"),s("mi",null,"a"),s("msup",null,[s("mi",null,"t"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",null,"−"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"a"),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"x=v_0 t+a t^2 / 2=\\left(v^2-v_0^2\\right) / 2 a \\text {. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7651em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/2"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2141em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])])])],-1),y=s("h3",{id:"_3-2-回転運動",tabindex:"-1"},[a("3.2: 回転運動 "),s("a",{class:"header-anchor",href:"#_3-2-回転運動","aria-label":'Permalink to "3.2: 回転運動"'},"​")],-1),v=s("ol",{start:"2"},[s("li",null,[a("回転運動は, 並進運動と似ていて:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",null,"ω")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",{separator:"true"},","),s("mi",null,"ε"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"ω"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",{mathvariant:"bold-italic"},"a")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"τ"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"v"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",null,"+"),s("mi",{mathvariant:"bold-italic"},"n"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} \\omega & =\\mathrm{d} \\varphi / \\mathrm{d} t, \\varepsilon=\\mathrm{d} \\omega / \\mathrm{d} t \\\\ \\boldsymbol{a} & =\\boldsymbol{\\tau} \\mathrm{d} v / \\mathrm{d} t+\\boldsymbol{n} v^2 / R \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.9221em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.9221em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.13472em"}},"τ")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"n")])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),b=t('

    3.3: 曲線運動

    1. 曲線運動は,ポイント 1 と同じだが,ベクトルは線速 度,加速度,経路長に置き換える.

    3.4: 剛体の運動

    ',3),x=s("ol",{start:"4"},[s("li",null,[a("剛体の運動: "),s("ul",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"v"),s("mi",null,"A")]),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mi",null,"B")]),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β")]),s("annotation",{encoding:"application/x-tex"},"v_A \\cos \\alpha=v_B \\cos \\beta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),a(" ここで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は剛体上の点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A")]),s("annotation",{encoding:"application/x-tex"},"A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" の速度, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"α")]),s("annotation",{encoding:"application/x-tex"},"\\alpha")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"β")]),s("annotation",{encoding:"application/x-tex"},"\\beta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),a(" は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" が直線 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" となす角.")]),s("li",null,[a("瞬間回転中心 (#質点の軌道 の曲率中心)は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{a}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"b")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{b}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])])])])]),a(" に下ろした垂線の交点. 又は もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")]),s("mo",null,"⊥"),s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A, \\boldsymbol{v}_B \\perp A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" ならば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" の先端を結ぶ 直線と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" の交点.")])])])],-1),w=s("h3",{id:"_3-5-非慣性系",tabindex:"-1"},[a("3.5: 非慣性系 "),s("a",{class:"header-anchor",href:"#_3-5-非慣性系","aria-label":'Permalink to "3.5: 非慣性系"'},"​")],-1),z=s("ol",{start:"5"},[s("li",null,[a("非慣性系:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.16em",columnalign:"right",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mspace",{width:"1em"}),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"0")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"0")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"1")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"ω"),s("mn",null,"2")]),s("mi",{mathvariant:"bold-italic"},"R"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mtext",null," ここで, "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])]),s("mo",null,"⊥"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"."),s("mtext",null," もし "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mo",null,"="),s("mn",null,"0"),s("mtext",null," なら "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])]),s("mo",null,"="),s("mn",null,"0.")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{array}{r} \\quad \\boldsymbol{v}_2=\\boldsymbol{v}_0+\\boldsymbol{v}_1, \\boldsymbol{a}_2=\\boldsymbol{a}_0+\\boldsymbol{a}_1+\\omega^2 \\boldsymbol{R}+\\boldsymbol{a}_{C o r} \\\\ \\text { ここで, } \\boldsymbol{a}_{C o r} \\perp \\boldsymbol{v}_1 . \\text { もし } \\boldsymbol{v}_1=0 \\text { なら } \\boldsymbol{a}_{C o r}=0 . \\end{array} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"arraycolsep",style:{width:"0.5em"}}),s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.45em"}},[s("span",{style:{top:"-3.61em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.00421em"}},"R")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-2.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"ここで"),s("span",{class:"mord"},", ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"."),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"もし"),s("span",{class:"mord"}," ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"なら"),s("span",{class:"mord"}," ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.95em"}},[s("span")])])])]),s("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])])])])],-1),_={id:"_3-6-弾道問題",tabindex:"-1"},k=s("a",{class:"header-anchor",href:"#_3-6-弾道問題","aria-label":'Permalink to "3.6: 弾道問題 "'},"​",-1),f=s("ol",{start:"6"},[s("li",null,[a("弾道問題:到達可能な範囲は"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"≤"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mn",null,"2"),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"−"),s("mi",null,"g"),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"2"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"y \\leq v_0^2 /(2 g)-g x^2 /\\left(2 v_0^2\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8304em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≤"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2141em","vertical-align":"-0.35em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])])])])])])]),a(" 最適な弾道では, 初速度と終速(衝突時の速度)が垂直 になる.")])],-1),M=t('

    3.7: 最短経路

    1. 最短経路を求めるには,Fermat と Huygens の原理が 使える.

    3.8: ベクトル

    1. ベクトル(速度,加速度)を求めるには,その向きと (場合によっては傾いた)ある軸への射影を求めれば 充分.
    ',4);function A(B,L,P,C,T,S){const n=e,m=p("Badge");return r(),c("div",null,[h,l(n,{readTime:"2",words:"473"}),g,d,u,y,v,b,x,w,z,s("h3",_,[a("3.6: 弾道問題 "),l(m,{type:"tip",text:"supplemental"}),a(),k]),f,M])}const j=i(o,[["render",A]]);export{V as __pageData,j as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_3.md.aadd6536.lean.js b/assets/academic_physics_ipho-formulas-jpn_3.md.6485844d.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_3.md.aadd6536.lean.js rename to assets/academic_physics_ipho-formulas-jpn_3.md.6485844d.lean.js index a7188f63..8445487f 100644 --- a/assets/academic_physics_ipho-formulas-jpn_3.md.aadd6536.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_3.md.6485844d.lean.js @@ -1 +1 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as l,k as s,a,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const V=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 3","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/3.md","filePath":"academic/physics/ipho-formulas-jpn/3.md","lastUpdated":1695377563000}'),o={name:"academic/physics/ipho-formulas-jpn/3.md"},h=s("h1",{id:"formulas-for-ipho-日本語版-section-3",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 3 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-3","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 3"'},"​")],-1),g=s("h2",{id:"_3-運動学",tabindex:"-1"},[a("3: 運動学 "),s("a",{class:"header-anchor",href:"#_3-運動学","aria-label":'Permalink to "3: 運動学"'},"​")],-1),d=s("h3",{id:"_3-1-質点",tabindex:"-1"},[a("3.1: 質点 "),s("a",{class:"header-anchor",href:"#_3-1-質点","aria-label":'Permalink to "3.1: 質点"'},"​")],-1),u=s("ol",null,[s("li",null,[a("質点または剛体の並進運動の場合(積分 → グラフの下 の面積):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"x")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"x"),s("mo",null,"="),s("mo",null,"∫"),s("mi",{mathvariant:"bold-italic"},"v"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"t"),s("mtext",null," など "),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"v")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"d"),s("mn",null,"2")]),s("mi",{mathvariant:"bold-italic"},"x")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("msup",null,[s("mi",null,"t"),s("mn",null,"2")])])]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"="),s("mo",null,"∫"),s("mi",{mathvariant:"bold-italic"},"a"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"t"),s("mo",null,"="),s("mo",null,"∫"),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"x"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("msubsup",null,[s("mi",null,"a"),s("mi",null,"x"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("mfrac",null,[s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{v}=\\frac{\\mathrm{d} \\boldsymbol{x}}{\\mathrm{d} t}, \\boldsymbol{x}=\\int \\boldsymbol{v} \\mathrm{d} t\\left(x=\\int v_x \\mathrm{~d} t \\text { など }\\right) \\\\ \\boldsymbol{a}=\\frac{\\mathrm{d} \\boldsymbol{v}}{\\mathrm{d} t}=\\frac{\\mathrm{d}^2 \\boldsymbol{x}}{\\mathrm{d} t^2}, \\boldsymbol{v}=\\int \\boldsymbol{a} \\mathrm{d} t \\\\ t=\\int v_x^{-1} \\mathrm{~d} x=\\int a_x^{-1} \\mathrm{~d} v_x, x=\\int \\frac{v_x}{a_x} \\mathrm{~d} v_x \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"7.8756em","vertical-align":"-3.6878em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1878em"}},[s("span",{style:{top:"-6.2289em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"など"),s("span",{class:"mord"}," ")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])])])]),s("span",{style:{top:"-3.4878em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.4911em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-0.9655em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1076em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.836em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6878em"}},[s("span")])])])])])])])])])])]),a(" もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(" が定数ならば, これらの積分は簡単に求めるこ とができて, 例えば"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mn",null,"0")]),s("mi",null,"t"),s("mo",null,"+"),s("mi",null,"a"),s("msup",null,[s("mi",null,"t"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",null,"−"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"a"),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"x=v_0 t+a t^2 / 2=\\left(v^2-v_0^2\\right) / 2 a \\text {. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7651em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/2"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2141em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])])])],-1),y=s("h3",{id:"_3-2-回転運動",tabindex:"-1"},[a("3.2: 回転運動 "),s("a",{class:"header-anchor",href:"#_3-2-回転運動","aria-label":'Permalink to "3.2: 回転運動"'},"​")],-1),v=s("ol",{start:"2"},[s("li",null,[a("回転運動は, 並進運動と似ていて:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",null,"ω")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",{separator:"true"},","),s("mi",null,"ε"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"ω"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",{mathvariant:"bold-italic"},"a")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"τ"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"v"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",null,"+"),s("mi",{mathvariant:"bold-italic"},"n"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} \\omega & =\\mathrm{d} \\varphi / \\mathrm{d} t, \\varepsilon=\\mathrm{d} \\omega / \\mathrm{d} t \\\\ \\boldsymbol{a} & =\\boldsymbol{\\tau} \\mathrm{d} v / \\mathrm{d} t+\\boldsymbol{n} v^2 / R \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.9221em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.9221em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.13472em"}},"τ")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"n")])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),b=t("",3),x=s("ol",{start:"4"},[s("li",null,[a("剛体の運動: "),s("ul",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"v"),s("mi",null,"A")]),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mi",null,"B")]),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β")]),s("annotation",{encoding:"application/x-tex"},"v_A \\cos \\alpha=v_B \\cos \\beta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),a(" ここで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は剛体上の点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A")]),s("annotation",{encoding:"application/x-tex"},"A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" の速度, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"α")]),s("annotation",{encoding:"application/x-tex"},"\\alpha")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"β")]),s("annotation",{encoding:"application/x-tex"},"\\beta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),a(" は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" が直線 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" となす角.")]),s("li",null,[a("瞬間回転中心 (#質点の軌道 の曲率中心)は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{a}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"b")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{b}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])])])])]),a(" に下ろした垂線の交点. 又は もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")]),s("mo",null,"⊥"),s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A, \\boldsymbol{v}_B \\perp A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" ならば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" の先端を結ぶ 直線と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" の交点.")])])])],-1),w=s("h3",{id:"_3-5-非慣性系",tabindex:"-1"},[a("3.5: 非慣性系 "),s("a",{class:"header-anchor",href:"#_3-5-非慣性系","aria-label":'Permalink to "3.5: 非慣性系"'},"​")],-1),z=s("ol",{start:"5"},[s("li",null,[a("非慣性系:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.16em",columnalign:"right",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mspace",{width:"1em"}),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"0")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"0")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"1")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"ω"),s("mn",null,"2")]),s("mi",{mathvariant:"bold-italic"},"R"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mtext",null," ここで, "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])]),s("mo",null,"⊥"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"."),s("mtext",null," もし "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mo",null,"="),s("mn",null,"0"),s("mtext",null," なら "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])]),s("mo",null,"="),s("mn",null,"0.")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{array}{r} \\quad \\boldsymbol{v}_2=\\boldsymbol{v}_0+\\boldsymbol{v}_1, \\boldsymbol{a}_2=\\boldsymbol{a}_0+\\boldsymbol{a}_1+\\omega^2 \\boldsymbol{R}+\\boldsymbol{a}_{C o r} \\\\ \\text { ここで, } \\boldsymbol{a}_{C o r} \\perp \\boldsymbol{v}_1 . \\text { もし } \\boldsymbol{v}_1=0 \\text { なら } \\boldsymbol{a}_{C o r}=0 . \\end{array} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"arraycolsep",style:{width:"0.5em"}}),s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.45em"}},[s("span",{style:{top:"-3.61em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.00421em"}},"R")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-2.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"ここで"),s("span",{class:"mord"},", ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"."),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"もし"),s("span",{class:"mord"}," ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"なら"),s("span",{class:"mord"}," ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.95em"}},[s("span")])])])]),s("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])])])])],-1),_={id:"_3-6-弾道問題",tabindex:"-1"},k=s("a",{class:"header-anchor",href:"#_3-6-弾道問題","aria-label":'Permalink to "3.6: 弾道問題 "'},"​",-1),f=s("ol",{start:"6"},[s("li",null,[a("弾道問題:到達可能な範囲は"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"≤"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mn",null,"2"),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"−"),s("mi",null,"g"),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"2"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"y \\leq v_0^2 /(2 g)-g x^2 /\\left(2 v_0^2\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8304em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≤"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2141em","vertical-align":"-0.35em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])])])])])])]),a(" 最適な弾道では, 初速度と終速(衝突時の速度)が垂直 になる.")])],-1),M=t("",4);function A(B,L,P,C,T,S){const n=e,m=p("Badge");return r(),c("div",null,[h,l(n,{readTime:"2",words:"473"}),g,d,u,y,v,b,x,w,z,s("h3",_,[a("3.6: 弾道問題 "),l(m,{type:"tip",text:"supplemental"}),a(),k]),f,M])}const j=i(o,[["render",A]]);export{V as __pageData,j as default}; +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as l,k as s,a,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const V=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 3","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/3.md","filePath":"academic/physics/ipho-formulas-jpn/3.md","lastUpdated":1699051935000}'),o={name:"academic/physics/ipho-formulas-jpn/3.md"},h=s("h1",{id:"formulas-for-ipho-日本語版-section-3",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 3 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-3","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 3"'},"​")],-1),g=s("h2",{id:"_3-運動学",tabindex:"-1"},[a("3: 運動学 "),s("a",{class:"header-anchor",href:"#_3-運動学","aria-label":'Permalink to "3: 運動学"'},"​")],-1),d=s("h3",{id:"_3-1-質点",tabindex:"-1"},[a("3.1: 質点 "),s("a",{class:"header-anchor",href:"#_3-1-質点","aria-label":'Permalink to "3.1: 質点"'},"​")],-1),u=s("ol",null,[s("li",null,[a("質点または剛体の並進運動の場合(積分 → グラフの下 の面積):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"x")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"x"),s("mo",null,"="),s("mo",null,"∫"),s("mi",{mathvariant:"bold-italic"},"v"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"t"),s("mtext",null," など "),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"v")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"d"),s("mn",null,"2")]),s("mi",{mathvariant:"bold-italic"},"x")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("msup",null,[s("mi",null,"t"),s("mn",null,"2")])])]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"="),s("mo",null,"∫"),s("mi",{mathvariant:"bold-italic"},"a"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"t"),s("mo",null,"="),s("mo",null,"∫"),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"x"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("msubsup",null,[s("mi",null,"a"),s("mi",null,"x"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("mi",null,"x"),s("mo",null,"="),s("mo",null,"∫"),s("mfrac",null,[s("msub",null,[s("mi",null,"v"),s("mi",null,"x")]),s("msub",null,[s("mi",null,"a"),s("mi",null,"x")])]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("msub",null,[s("mi",null,"v"),s("mi",null,"x")])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{v}=\\frac{\\mathrm{d} \\boldsymbol{x}}{\\mathrm{d} t}, \\boldsymbol{x}=\\int \\boldsymbol{v} \\mathrm{d} t\\left(x=\\int v_x \\mathrm{~d} t \\text { など }\\right) \\\\ \\boldsymbol{a}=\\frac{\\mathrm{d} \\boldsymbol{v}}{\\mathrm{d} t}=\\frac{\\mathrm{d}^2 \\boldsymbol{x}}{\\mathrm{d} t^2}, \\boldsymbol{v}=\\int \\boldsymbol{a} \\mathrm{d} t \\\\ t=\\int v_x^{-1} \\mathrm{~d} x=\\int a_x^{-1} \\mathrm{~d} v_x, x=\\int \\frac{v_x}{a_x} \\mathrm{~d} v_x \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"7.8756em","vertical-align":"-3.6878em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1878em"}},[s("span",{style:{top:"-6.2289em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"など"),s("span",{class:"mord"}," ")]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])])])]),s("span",{style:{top:"-3.4878em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.4911em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-0.9655em"}},[s("span",{class:"pstrut",style:{height:"3.4911em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1076em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.836em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6878em"}},[s("span")])])])])])])])])])])]),a(" もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(" が定数ならば, これらの積分は簡単に求めるこ とができて, 例えば"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mn",null,"0")]),s("mi",null,"t"),s("mo",null,"+"),s("mi",null,"a"),s("msup",null,[s("mi",null,"t"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mo",null,"−"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2"),s("mi",null,"a"),s("mtext",null,". ")]),s("annotation",{encoding:"application/x-tex"},"x=v_0 t+a t^2 / 2=\\left(v^2-v_0^2\\right) / 2 a \\text {. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7651em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"t"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/2"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2141em","vertical-align":"-0.35em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/2"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord text"},[s("span",{class:"mord"},". ")])])])])])])])],-1),y=s("h3",{id:"_3-2-回転運動",tabindex:"-1"},[a("3.2: 回転運動 "),s("a",{class:"header-anchor",href:"#_3-2-回転運動","aria-label":'Permalink to "3.2: 回転運動"'},"​")],-1),v=s("ol",{start:"2"},[s("li",null,[a("回転運動は, 並進運動と似ていて:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",null,"ω")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",{separator:"true"},","),s("mi",null,"ε"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"ω"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mi",{mathvariant:"bold-italic"},"a")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"τ"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"v"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",null,"+"),s("mi",{mathvariant:"bold-italic"},"n"),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} \\omega & =\\mathrm{d} \\varphi / \\mathrm{d} t, \\varepsilon=\\mathrm{d} \\omega / \\mathrm{d} t \\\\ \\boldsymbol{a} & =\\boldsymbol{\\tau} \\mathrm{d} v / \\mathrm{d} t+\\boldsymbol{n} v^2 / R \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.9221em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.9221em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.13472em"}},"τ")])]),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"n")])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),b=t("",3),x=s("ol",{start:"4"},[s("li",null,[a("剛体の運動: "),s("ul",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"v"),s("mi",null,"A")]),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"α"),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mi",null,"B")]),s("mi",null,"cos"),s("mo",null,"⁡"),s("mi",null,"β")]),s("annotation",{encoding:"application/x-tex"},"v_A \\cos \\alpha=v_B \\cos \\beta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),a(" ここで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は剛体上の点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A")]),s("annotation",{encoding:"application/x-tex"},"A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" の速度, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"α")]),s("annotation",{encoding:"application/x-tex"},"\\alpha")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"β")]),s("annotation",{encoding:"application/x-tex"},"\\beta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),a(" は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" が直線 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" となす角.")]),s("li",null,[a("瞬間回転中心 (#質点の軌道 の曲率中心)は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"a")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{a}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"b")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{b}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"b")])])])])]),a(" に下ろした垂線の交点. 又は もし "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")]),s("mo",null,"⊥"),s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A, \\boldsymbol{v}_B \\perp A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" ならば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"A")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"A")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"B")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05017em"}},"B")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" の先端を結ぶ 直線と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"A B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" の交点.")])])])],-1),w=s("h3",{id:"_3-5-非慣性系",tabindex:"-1"},[a("3.5: 非慣性系 "),s("a",{class:"header-anchor",href:"#_3-5-非慣性系","aria-label":'Permalink to "3.5: 非慣性系"'},"​")],-1),z=s("ol",{start:"5"},[s("li",null,[a("非慣性系:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.16em",columnalign:"right",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mspace",{width:"1em"}),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"0")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"0")]),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mn",null,"1")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"ω"),s("mn",null,"2")]),s("mi",{mathvariant:"bold-italic"},"R"),s("mo",null,"+"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mtext",null," ここで, "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])]),s("mo",null,"⊥"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"."),s("mtext",null," もし "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mn",null,"1")]),s("mo",null,"="),s("mn",null,"0"),s("mtext",null," なら "),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"a"),s("mrow",null,[s("mi",null,"C"),s("mi",null,"o"),s("mi",null,"r")])]),s("mo",null,"="),s("mn",null,"0.")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{array}{r} \\quad \\boldsymbol{v}_2=\\boldsymbol{v}_0+\\boldsymbol{v}_1, \\boldsymbol{a}_2=\\boldsymbol{a}_0+\\boldsymbol{a}_1+\\omega^2 \\boldsymbol{R}+\\boldsymbol{a}_{C o r} \\\\ \\text { ここで, } \\boldsymbol{a}_{C o r} \\perp \\boldsymbol{v}_1 . \\text { もし } \\boldsymbol{v}_1=0 \\text { なら } \\boldsymbol{a}_{C o r}=0 . \\end{array} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"arraycolsep",style:{width:"0.5em"}}),s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.45em"}},[s("span",{style:{top:"-3.61em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.00421em"}},"R")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-2.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"ここで"),s("span",{class:"mord"},", ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"⊥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"."),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"もし"),s("span",{class:"mord"}," ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mord text"},[s("span",{class:"mord"}," "),s("span",{class:"mord cjk_fallback"},"なら"),s("span",{class:"mord"}," ")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"or")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"0.")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.95em"}},[s("span")])])])]),s("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])])])])],-1),_={id:"_3-6-弾道問題",tabindex:"-1"},k=s("a",{class:"header-anchor",href:"#_3-6-弾道問題","aria-label":'Permalink to "3.6: 弾道問題 "'},"​",-1),f=s("ol",{start:"6"},[s("li",null,[a("弾道問題:到達可能な範囲は"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y"),s("mo",null,"≤"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mo",{stretchy:"false"},"("),s("mn",null,"2"),s("mi",null,"g"),s("mo",{stretchy:"false"},")"),s("mo",null,"−"),s("mi",null,"g"),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"2"),s("msubsup",null,[s("mi",null,"v"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"y \\leq v_0^2 /(2 g)-g x^2 /\\left(2 v_0^2\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8304em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≤"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1141em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2141em","vertical-align":"-0.35em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])])])])])])]),a(" 最適な弾道では, 初速度と終速(衝突時の速度)が垂直 になる.")])],-1),M=t("",4);function A(B,L,P,C,T,S){const n=e,m=p("Badge");return r(),c("div",null,[h,l(n,{readTime:"2",words:"473"}),g,d,u,y,v,b,x,w,z,s("h3",_,[a("3.6: 弾道問題 "),l(m,{type:"tip",text:"supplemental"}),a(),k]),f,M])}const j=i(o,[["render",A]]);export{V as __pageData,j as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_4.md.67c0b4f9.js b/assets/academic_physics_ipho-formulas-jpn_4.md.47f0821f.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_4.md.67c0b4f9.js rename to assets/academic_physics_ipho-formulas-jpn_4.md.47f0821f.js index 1fc058af..261db708 100644 --- a/assets/academic_physics_ipho-formulas-jpn_4.md.67c0b4f9.js +++ b/assets/academic_physics_ipho-formulas-jpn_4.md.47f0821f.js @@ -1,4 +1,4 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as l,k as s,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const bs=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 4","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/4.md","filePath":"academic/physics/ipho-formulas-jpn/4.md","lastUpdated":1695377563000}'),h={name:"academic/physics/ipho-formulas-jpn/4.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-4",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 4 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-4","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 4"'},"​")],-1),g=n('

    4: 力学

    4.1: 剛体の二次元的な平衡

    1. 剛体の二次元的な平衡 : 力についての 2 つの式とトル クについての 1 つの式. 1 (又は 2 )個の力についての 式は 1(又は 2)個のトルクについての式で代用でき る. トルクの方が良い場合が多く,原点を適切に選択 することで「退屈な」力を消すことができる. もし 2 点 のみに力がかかっているならば,(正味の)力がかかっ ている直線は一致する. 3 点であれば, 3 つの直線は 1 点で交わる.

    4.2: 垂直抗力

    ',4),u=s("ol",{start:"2"},[s("li",null,[a("垂直抗力と摩擦力は 1 つの力に合成でき, 垂直抗力に 対して "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"arctan"),s("mo",null,"⁡"),s("mi",null,"μ")]),s("annotation",{encoding:"application/x-tex"},"\\arctan \\mu")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),s("span",{class:"mop"},"arctan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"μ")])])]),a(" の角度で接触点に加わる.")])],-1),d=s("h3",{id:"_4-3-並進運動と回転運動",tabindex:"-1"},[a("4.3: 並進運動と回転運動 "),s("a",{class:"header-anchor",href:"#_4-3-並進運動と回転運動","aria-label":'Permalink to "4.3: 並進運動と回転運動"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("並進運動と回転運動についての Newton の第二法則:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",null,"m"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"M"),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"bold-italic"},"ε"),s("mspace",{width:"1em"}),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"M"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"F"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}=m \\boldsymbol{a}, \\boldsymbol{M}=I \\boldsymbol{\\varepsilon} \\quad(\\boldsymbol{M}=\\boldsymbol{r} \\times \\boldsymbol{F}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8805em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"ε")])]),s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mclose"},")")])])])])]),a(" 二次元の場合には "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"M")]),s("annotation",{encoding:"application/x-tex"},"M")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ε")]),s("annotation",{encoding:"application/x-tex"},"\\varepsilon")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"ε")])])]),a(" は本質的にスカラーで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"M"),s("mo",null,"="),s("mi",null,"F"),s("mi",null,"l"),s("mo",null,"="),s("msub",null,[s("mi",null,"F"),s("mi",null,"t")]),s("mi",null,"r"),s("mo",{stretchy:"false"},"("),s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"M=F l=F_t r(l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"Fl"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2806em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"t")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(" は力のうでの長さ "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])])])],-1),v=s("h3",{id:"_4-4-一般化座標",tabindex:"-1"},[a("4.4: 一般化座標 "),s("a",{class:"header-anchor",href:"#_4-4-一般化座標","aria-label":'Permalink to "4.4: 一般化座標"'},"​")],-1),b=s("ol",{start:"4"},[s("li",null,[a("一般化座標. 系の状態が 1 つの変数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ξ")]),s("annotation",{encoding:"application/x-tex"},"\\xi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")])])]),a(" とその時間微分 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"ξ"),s("mo",null,"˙")])]),s("annotation",{encoding:"application/x-tex"},"\\dot{\\xi}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1257em","vertical-align":"-0.1944em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")]),s("span",{style:{top:"-3.2634em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.0278em"}},[s("span",{class:"mord"},"˙")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])])])])]),a(" で表され,ポテンシャルエネルギーが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mi",null,"U"),s("mo",{stretchy:"false"},"("),s("mi",null,"ξ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"U=U(\\xi)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"mclose"},")")])])]),a(", 運動エネルギーが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"K"),s("mo",null,"="),s("mi",null,"μ"),s("msup",null,[s("mi",null,"ξ"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")]),s("annotation",{encoding:"application/x-tex"},"K=\\mu \\xi^2 / 2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/2")])])]),a(" であるならば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"μ"),s("mover",{accent:"true"},[s("mi",null,"ξ"),s("mo",null,"¨")]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\mu \\ddot{\\xi}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1257em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")]),s("span",{style:{top:"-3.2634em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1389em"}},[s("span",{class:"mord"},"¨")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"−"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"U"),s("mo",{stretchy:"false"},"("),s("mi",null,"ξ"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"ξ")]),s("annotation",{encoding:"application/x-tex"},"-\\mathrm{d} U(\\xi) / \\mathrm{d} \\xi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")])])]),a(". (したがって並進運動では, 力はポテン シャルエネルギーの微分)")])],-1),x=s("h3",{id:"_4-5-系質点",tabindex:"-1"},[a("4.5: 系質点 "),s("a",{class:"header-anchor",href:"#_4-5-系質点","aria-label":'Permalink to "4.5: 系質点"'},"​")],-1),w=s("ol",{start:"5"},[s("li",null,[a("系が質点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"m"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"m_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" で構成されているとき:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"c")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mi",{mathvariant:"normal"},"/"),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"j")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"P"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"i")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"bold-italic"},"L"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"i")]),s("mo",{separator:"true"},","),s("mi",null,"K"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"i"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",null,"I"),s("mi",null,"z")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msubsup",null,[s("mi",null,"x"),s("mi",null,"i"),s("mn",null,"2")]),s("mo",null,"+"),s("msubsup",null,[s("mi",null,"y"),s("mi",null,"i"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"∫"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"y"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"m")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\boldsymbol{r}_c=\\sum m_i \\boldsymbol{r}_i / \\sum m_j, \\boldsymbol{P}=\\sum m_i \\boldsymbol{v}_i \\\\ & \\boldsymbol{L}=\\sum m_i \\boldsymbol{r}_i \\times \\boldsymbol{v}_i, K=\\sum m_i v_i^2 / 2 \\\\ & I_z=\\sum m_i\\left(x_i^2+y_i^2\\right)=\\int\\left(x^2+y^2\\right) \\mathrm{d} m \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"7.8223em","vertical-align":"-3.6611em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1611em"}},[s("span",{style:{top:"-6.4711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.5711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.3611em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-0.3589em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6611em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1611em"}},[s("span",{style:{top:"-6.4711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-4.5711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/2")])]),s("span",{style:{top:"-2.3611em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-0.3589em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"})])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6611em"}},[s("span")])])])])])])])])])])])])],-1),z=s("h3",{id:"_4-6-質量中心の速度",tabindex:"-1"},[a("4.6: 質量中心の速度 "),s("a",{class:"header-anchor",href:"#_4-6-質量中心の速度","aria-label":'Permalink to "4.6: 質量中心の速度"'},"​")],-1),k=s("ol",{start:"6"},[s("li",null,[a("質量中心の速度が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" であるような系 (添え字 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(" は質量 中心についての物理量であることを示す):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"L"),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"L"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"R"),s("mi",null,"c")]),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")]),s("mo",{separator:"true"},","),s("mi",null,"K"),s("mo",null,"="),s("msub",null,[s("mi",null,"K"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"c"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"P"),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"P"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},".")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{L}=\\boldsymbol{L}_c+M_{\\Sigma} \\boldsymbol{R}_c \\times \\boldsymbol{v}_c, K=K_c+M_{\\Sigma} v_c^2 / 2 \\\\ \\boldsymbol{P}=\\boldsymbol{P}_c+M_{\\Sigma} \\boldsymbol{v}_c . \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.8979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.00421em"}},"R")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/2")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},".")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),_=s("h3",{id:"_4-7-steiner-定理",tabindex:"-1"},[a("4.7: Steiner 定理 "),s("a",{class:"header-anchor",href:"#_4-7-steiner-定理","aria-label":'Permalink to "4.7: Steiner 定理"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("Steiner の定理(平行軸の定理)も同じような形で は質量中心の回転軸からの距離):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"="),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mo",null,"+"),s("mi",null,"m"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"I=I_c+m b^2 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8641em"}}),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])])])],-1),f=s("h3",{id:"_4-8-ポイント-6",tabindex:"-1"},[a("4.8: ポイント 6 "),s("a",{class:"header-anchor",href:"#_4-8-ポイント-6","aria-label":'Permalink to "4.8: ポイント 6"'},"​")],-1),L=s("ol",{start:"8"},[s("li",null,[a("ポイント 6 の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"P")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{P}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"L")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])])])])]),a(" を用いて, Newton の第二法則 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"P"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"L"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}_{\\Sigma}=\\mathrm{d} \\boldsymbol{P} / \\mathrm{d} t, \\boldsymbol{M}_{\\Sigma}=\\mathrm{d} \\boldsymbol{L} / \\mathrm{d} t ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8361em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])])])])])])],-1),P=s("h3",{id:"_4-9-ポイント-5",tabindex:"-1"},[a("4.9: ポイント 5 "),s("a",{class:"header-anchor",href:"#_4-9-ポイント-5","aria-label":'Permalink to "4.9: ポイント 5"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("ポイント 5 にに加えて,質量中心を通る "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"z")]),s("annotation",{encoding:"application/x-tex"},"z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")])])]),a(" 軸に対する慣性モ一メントは "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mrow",null,[s("mi",null,"z"),s("mn",null,"0")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"I_{z 0}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",{separator:"true"},","),s("mi",null,"j")])]),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"m"),s("mi",null,"j")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mi",null,"j")]),s("mo",{fence:"true"},")")]),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"y"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"y"),s("mi",null,"j")]),s("mo",{fence:"true"},")")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"2"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"\\sum_{i, j} m_i m_j\\left[\\left(x_i-x_j\\right)^2+\\left(y_i-y_j\\right)^2\\right] /\\left(2 M_{\\Sigma}\\right)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.8em","vertical-align":"-0.65em"}}),s("span",{class:"mop"},[s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.162em"}},[s("span",{style:{top:"-2.4003em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4358em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size2"},"[")]),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size2"},"]")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])],-1),F=s("h3",{id:"_4-10-原点に対する慣性",tabindex:"-1"},[a("4.10: 原点に対する慣性 "),s("a",{class:"header-anchor",href:"#_4-10-原点に対する慣性","aria-label":'Permalink to "4.10: 原点に対する慣性"'},"​")],-1),T=s("ol",{start:"10"},[s("li",null,[a("原点に対する慣性モ一メント "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"θ"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msubsup",null,[s("mi",null,"r"),s("mi",null,"i"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\theta=\\sum m_i r_i^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0728em","vertical-align":"-0.2587em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-2.4413em","margin-left":"-0.0278em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2587em"}},[s("span")])])])])])])])]),a(" は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"θ"),s("mo",null,"="),s("msub",null,[s("mi",null,"I"),s("mi",null,"x")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"y")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"z")])]),s("annotation",{encoding:"application/x-tex"},"2 \\theta=I_x+I_y+I_z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9694em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" を用いることで二次元物体や等 方性のある物体の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mi",null,"z")])]),s("annotation",{encoding:"application/x-tex"},"I_z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" を計算するのに有用.")])],-1),S=s("h3",{id:"_4-11-相当単振子の長",tabindex:"-1"},[a("4.11: 相当単振子の長 "),s("a",{class:"header-anchor",href:"#_4-11-相当単振子の長","aria-label":'Permalink to "4.11: 相当単振子の長"'},"​")],-1),j=s("ol",{start:"11"},[s("li",null,[a("相当単振子の長さが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")])]),s("annotation",{encoding:"application/x-tex"},"\\tilde{l}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9313em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])])])])]),a(" である物理振子 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"ω"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"g"),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"l"),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m"),s("mi",null,"l"),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"ω"),s("mo",{stretchy:"false"},"("),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"ω"),s("mo",{stretchy:"false"},"("),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")]),s("mo",null,"−"),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("msqrt",null,[s("mrow",null,[s("mi",null,"g"),s("mi",{mathvariant:"normal"},"/"),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")])])]),s("mo",{separator:"true"},","),s("mspace",{width:"1em"}),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")]),s("mo",null,"="),s("mi",null,"l"),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m"),s("mi",null,"l")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\omega^2(l)=g /\\left(l+I_c / m l\\right) \\\\ & \\omega(l)=\\omega(\\tilde{l}-l)=\\sqrt{g / \\tilde{l}}, \\quad \\tilde{l}=l+I_c / m l \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"5.1641em","vertical-align":"-2.3321em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.8321em"}},[s("span",{style:{top:"-5.3425em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-3.3079em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.7025em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3321em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.8321em"}},[s("span",{style:{top:"-5.3425em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])]),s("span",{style:{top:"-3.3079em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mopen"},"("),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3745em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"/"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])])])]),s("span",{style:{top:"-3.3345em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as l,k as s,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const bs=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 4","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/4.md","filePath":"academic/physics/ipho-formulas-jpn/4.md","lastUpdated":1699051935000}'),h={name:"academic/physics/ipho-formulas-jpn/4.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-4",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 4 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-4","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 4"'},"​")],-1),g=n('

    4: 力学

    4.1: 剛体の二次元的な平衡

    1. 剛体の二次元的な平衡 : 力についての 2 つの式とトル クについての 1 つの式. 1 (又は 2 )個の力についての 式は 1(又は 2)個のトルクについての式で代用でき る. トルクの方が良い場合が多く,原点を適切に選択 することで「退屈な」力を消すことができる. もし 2 点 のみに力がかかっているならば,(正味の)力がかかっ ている直線は一致する. 3 点であれば, 3 つの直線は 1 点で交わる.

    4.2: 垂直抗力

    ',4),u=s("ol",{start:"2"},[s("li",null,[a("垂直抗力と摩擦力は 1 つの力に合成でき, 垂直抗力に 対して "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"arctan"),s("mo",null,"⁡"),s("mi",null,"μ")]),s("annotation",{encoding:"application/x-tex"},"\\arctan \\mu")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),s("span",{class:"mop"},"arctan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"μ")])])]),a(" の角度で接触点に加わる.")])],-1),d=s("h3",{id:"_4-3-並進運動と回転運動",tabindex:"-1"},[a("4.3: 並進運動と回転運動 "),s("a",{class:"header-anchor",href:"#_4-3-並進運動と回転運動","aria-label":'Permalink to "4.3: 並進運動と回転運動"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("並進運動と回転運動についての Newton の第二法則:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",null,"m"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"M"),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"bold-italic"},"ε"),s("mspace",{width:"1em"}),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"M"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"F"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}=m \\boldsymbol{a}, \\boldsymbol{M}=I \\boldsymbol{\\varepsilon} \\quad(\\boldsymbol{M}=\\boldsymbol{r} \\times \\boldsymbol{F}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8805em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"ε")])]),s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mclose"},")")])])])])]),a(" 二次元の場合には "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"M")]),s("annotation",{encoding:"application/x-tex"},"M")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ε")]),s("annotation",{encoding:"application/x-tex"},"\\varepsilon")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"ε")])])]),a(" は本質的にスカラーで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"M"),s("mo",null,"="),s("mi",null,"F"),s("mi",null,"l"),s("mo",null,"="),s("msub",null,[s("mi",null,"F"),s("mi",null,"t")]),s("mi",null,"r"),s("mo",{stretchy:"false"},"("),s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"M=F l=F_t r(l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"Fl"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2806em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"t")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(" は力のうでの長さ "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])])])],-1),v=s("h3",{id:"_4-4-一般化座標",tabindex:"-1"},[a("4.4: 一般化座標 "),s("a",{class:"header-anchor",href:"#_4-4-一般化座標","aria-label":'Permalink to "4.4: 一般化座標"'},"​")],-1),b=s("ol",{start:"4"},[s("li",null,[a("一般化座標. 系の状態が 1 つの変数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ξ")]),s("annotation",{encoding:"application/x-tex"},"\\xi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")])])]),a(" とその時間微分 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"ξ"),s("mo",null,"˙")])]),s("annotation",{encoding:"application/x-tex"},"\\dot{\\xi}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1257em","vertical-align":"-0.1944em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")]),s("span",{style:{top:"-3.2634em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.0278em"}},[s("span",{class:"mord"},"˙")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])])])])]),a(" で表され,ポテンシャルエネルギーが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mi",null,"U"),s("mo",{stretchy:"false"},"("),s("mi",null,"ξ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"U=U(\\xi)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"mclose"},")")])])]),a(", 運動エネルギーが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"K"),s("mo",null,"="),s("mi",null,"μ"),s("msup",null,[s("mi",null,"ξ"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")]),s("annotation",{encoding:"application/x-tex"},"K=\\mu \\xi^2 / 2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/2")])])]),a(" であるならば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"μ"),s("mover",{accent:"true"},[s("mi",null,"ξ"),s("mo",null,"¨")]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\mu \\ddot{\\xi}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1257em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")]),s("span",{style:{top:"-3.2634em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1389em"}},[s("span",{class:"mord"},"¨")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"−"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"U"),s("mo",{stretchy:"false"},"("),s("mi",null,"ξ"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"ξ")]),s("annotation",{encoding:"application/x-tex"},"-\\mathrm{d} U(\\xi) / \\mathrm{d} \\xi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")])])]),a(". (したがって並進運動では, 力はポテン シャルエネルギーの微分)")])],-1),x=s("h3",{id:"_4-5-系質点",tabindex:"-1"},[a("4.5: 系質点 "),s("a",{class:"header-anchor",href:"#_4-5-系質点","aria-label":'Permalink to "4.5: 系質点"'},"​")],-1),w=s("ol",{start:"5"},[s("li",null,[a("系が質点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"m"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"m_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" で構成されているとき:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"c")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mi",{mathvariant:"normal"},"/"),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"j")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"P"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"i")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"bold-italic"},"L"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"i")]),s("mo",{separator:"true"},","),s("mi",null,"K"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"i"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",null,"I"),s("mi",null,"z")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msubsup",null,[s("mi",null,"x"),s("mi",null,"i"),s("mn",null,"2")]),s("mo",null,"+"),s("msubsup",null,[s("mi",null,"y"),s("mi",null,"i"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"∫"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"y"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"m")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\boldsymbol{r}_c=\\sum m_i \\boldsymbol{r}_i / \\sum m_j, \\boldsymbol{P}=\\sum m_i \\boldsymbol{v}_i \\\\ & \\boldsymbol{L}=\\sum m_i \\boldsymbol{r}_i \\times \\boldsymbol{v}_i, K=\\sum m_i v_i^2 / 2 \\\\ & I_z=\\sum m_i\\left(x_i^2+y_i^2\\right)=\\int\\left(x^2+y^2\\right) \\mathrm{d} m \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"7.8223em","vertical-align":"-3.6611em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1611em"}},[s("span",{style:{top:"-6.4711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.5711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.3611em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-0.3589em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6611em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1611em"}},[s("span",{style:{top:"-6.4711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-4.5711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/2")])]),s("span",{style:{top:"-2.3611em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-0.3589em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"})])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6611em"}},[s("span")])])])])])])])])])])])])],-1),z=s("h3",{id:"_4-6-質量中心の速度",tabindex:"-1"},[a("4.6: 質量中心の速度 "),s("a",{class:"header-anchor",href:"#_4-6-質量中心の速度","aria-label":'Permalink to "4.6: 質量中心の速度"'},"​")],-1),k=s("ol",{start:"6"},[s("li",null,[a("質量中心の速度が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" であるような系 (添え字 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(" は質量 中心についての物理量であることを示す):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"L"),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"L"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"R"),s("mi",null,"c")]),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")]),s("mo",{separator:"true"},","),s("mi",null,"K"),s("mo",null,"="),s("msub",null,[s("mi",null,"K"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"c"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"P"),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"P"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},".")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{L}=\\boldsymbol{L}_c+M_{\\Sigma} \\boldsymbol{R}_c \\times \\boldsymbol{v}_c, K=K_c+M_{\\Sigma} v_c^2 / 2 \\\\ \\boldsymbol{P}=\\boldsymbol{P}_c+M_{\\Sigma} \\boldsymbol{v}_c . \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.8979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.00421em"}},"R")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/2")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},".")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),_=s("h3",{id:"_4-7-steiner-定理",tabindex:"-1"},[a("4.7: Steiner 定理 "),s("a",{class:"header-anchor",href:"#_4-7-steiner-定理","aria-label":'Permalink to "4.7: Steiner 定理"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("Steiner の定理(平行軸の定理)も同じような形で は質量中心の回転軸からの距離):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"="),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mo",null,"+"),s("mi",null,"m"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"I=I_c+m b^2 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8641em"}}),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])])])],-1),f=s("h3",{id:"_4-8-ポイント-6",tabindex:"-1"},[a("4.8: ポイント 6 "),s("a",{class:"header-anchor",href:"#_4-8-ポイント-6","aria-label":'Permalink to "4.8: ポイント 6"'},"​")],-1),L=s("ol",{start:"8"},[s("li",null,[a("ポイント 6 の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"P")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{P}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"L")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])])])])]),a(" を用いて, Newton の第二法則 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"P"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"L"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}_{\\Sigma}=\\mathrm{d} \\boldsymbol{P} / \\mathrm{d} t, \\boldsymbol{M}_{\\Sigma}=\\mathrm{d} \\boldsymbol{L} / \\mathrm{d} t ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8361em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])])])])])])],-1),P=s("h3",{id:"_4-9-ポイント-5",tabindex:"-1"},[a("4.9: ポイント 5 "),s("a",{class:"header-anchor",href:"#_4-9-ポイント-5","aria-label":'Permalink to "4.9: ポイント 5"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("ポイント 5 にに加えて,質量中心を通る "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"z")]),s("annotation",{encoding:"application/x-tex"},"z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")])])]),a(" 軸に対する慣性モ一メントは "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mrow",null,[s("mi",null,"z"),s("mn",null,"0")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"I_{z 0}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",{separator:"true"},","),s("mi",null,"j")])]),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"m"),s("mi",null,"j")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mi",null,"j")]),s("mo",{fence:"true"},")")]),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"y"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"y"),s("mi",null,"j")]),s("mo",{fence:"true"},")")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"2"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"\\sum_{i, j} m_i m_j\\left[\\left(x_i-x_j\\right)^2+\\left(y_i-y_j\\right)^2\\right] /\\left(2 M_{\\Sigma}\\right)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.8em","vertical-align":"-0.65em"}}),s("span",{class:"mop"},[s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.162em"}},[s("span",{style:{top:"-2.4003em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4358em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size2"},"[")]),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size2"},"]")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])],-1),F=s("h3",{id:"_4-10-原点に対する慣性",tabindex:"-1"},[a("4.10: 原点に対する慣性 "),s("a",{class:"header-anchor",href:"#_4-10-原点に対する慣性","aria-label":'Permalink to "4.10: 原点に対する慣性"'},"​")],-1),T=s("ol",{start:"10"},[s("li",null,[a("原点に対する慣性モ一メント "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"θ"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msubsup",null,[s("mi",null,"r"),s("mi",null,"i"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\theta=\\sum m_i r_i^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0728em","vertical-align":"-0.2587em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-2.4413em","margin-left":"-0.0278em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2587em"}},[s("span")])])])])])])])]),a(" は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"θ"),s("mo",null,"="),s("msub",null,[s("mi",null,"I"),s("mi",null,"x")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"y")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"z")])]),s("annotation",{encoding:"application/x-tex"},"2 \\theta=I_x+I_y+I_z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9694em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" を用いることで二次元物体や等 方性のある物体の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mi",null,"z")])]),s("annotation",{encoding:"application/x-tex"},"I_z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" を計算するのに有用.")])],-1),S=s("h3",{id:"_4-11-相当単振子の長",tabindex:"-1"},[a("4.11: 相当単振子の長 "),s("a",{class:"header-anchor",href:"#_4-11-相当単振子の長","aria-label":'Permalink to "4.11: 相当単振子の長"'},"​")],-1),j=s("ol",{start:"11"},[s("li",null,[a("相当単振子の長さが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")])]),s("annotation",{encoding:"application/x-tex"},"\\tilde{l}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9313em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])])])])]),a(" である物理振子 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"ω"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"g"),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"l"),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m"),s("mi",null,"l"),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"ω"),s("mo",{stretchy:"false"},"("),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"ω"),s("mo",{stretchy:"false"},"("),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")]),s("mo",null,"−"),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("msqrt",null,[s("mrow",null,[s("mi",null,"g"),s("mi",{mathvariant:"normal"},"/"),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")])])]),s("mo",{separator:"true"},","),s("mspace",{width:"1em"}),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")]),s("mo",null,"="),s("mi",null,"l"),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m"),s("mi",null,"l")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\omega^2(l)=g /\\left(l+I_c / m l\\right) \\\\ & \\omega(l)=\\omega(\\tilde{l}-l)=\\sqrt{g / \\tilde{l}}, \\quad \\tilde{l}=l+I_c / m l \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"5.1641em","vertical-align":"-2.3321em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.8321em"}},[s("span",{style:{top:"-5.3425em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-3.3079em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.7025em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3321em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.8321em"}},[s("span",{style:{top:"-5.3425em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])]),s("span",{style:{top:"-3.3079em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mopen"},"("),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3745em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"/"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])])])]),s("span",{style:{top:"-3.3345em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 l0 -0 c4,-6.7,10,-10,18,-10 H400000v40 H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7 diff --git a/assets/academic_physics_ipho-formulas-jpn_4.md.67c0b4f9.lean.js b/assets/academic_physics_ipho-formulas-jpn_4.md.47f0821f.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_4.md.67c0b4f9.lean.js rename to assets/academic_physics_ipho-formulas-jpn_4.md.47f0821f.lean.js index 90d880ee..44da3c5f 100644 --- a/assets/academic_physics_ipho-formulas-jpn_4.md.67c0b4f9.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_4.md.47f0821f.lean.js @@ -1,4 +1,4 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as l,k as s,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const bs=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 4","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/4.md","filePath":"academic/physics/ipho-formulas-jpn/4.md","lastUpdated":1695377563000}'),h={name:"academic/physics/ipho-formulas-jpn/4.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-4",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 4 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-4","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 4"'},"​")],-1),g=n("",4),u=s("ol",{start:"2"},[s("li",null,[a("垂直抗力と摩擦力は 1 つの力に合成でき, 垂直抗力に 対して "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"arctan"),s("mo",null,"⁡"),s("mi",null,"μ")]),s("annotation",{encoding:"application/x-tex"},"\\arctan \\mu")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),s("span",{class:"mop"},"arctan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"μ")])])]),a(" の角度で接触点に加わる.")])],-1),d=s("h3",{id:"_4-3-並進運動と回転運動",tabindex:"-1"},[a("4.3: 並進運動と回転運動 "),s("a",{class:"header-anchor",href:"#_4-3-並進運動と回転運動","aria-label":'Permalink to "4.3: 並進運動と回転運動"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("並進運動と回転運動についての Newton の第二法則:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",null,"m"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"M"),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"bold-italic"},"ε"),s("mspace",{width:"1em"}),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"M"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"F"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}=m \\boldsymbol{a}, \\boldsymbol{M}=I \\boldsymbol{\\varepsilon} \\quad(\\boldsymbol{M}=\\boldsymbol{r} \\times \\boldsymbol{F}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8805em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"ε")])]),s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mclose"},")")])])])])]),a(" 二次元の場合には "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"M")]),s("annotation",{encoding:"application/x-tex"},"M")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ε")]),s("annotation",{encoding:"application/x-tex"},"\\varepsilon")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"ε")])])]),a(" は本質的にスカラーで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"M"),s("mo",null,"="),s("mi",null,"F"),s("mi",null,"l"),s("mo",null,"="),s("msub",null,[s("mi",null,"F"),s("mi",null,"t")]),s("mi",null,"r"),s("mo",{stretchy:"false"},"("),s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"M=F l=F_t r(l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"Fl"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2806em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"t")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(" は力のうでの長さ "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])])])],-1),v=s("h3",{id:"_4-4-一般化座標",tabindex:"-1"},[a("4.4: 一般化座標 "),s("a",{class:"header-anchor",href:"#_4-4-一般化座標","aria-label":'Permalink to "4.4: 一般化座標"'},"​")],-1),b=s("ol",{start:"4"},[s("li",null,[a("一般化座標. 系の状態が 1 つの変数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ξ")]),s("annotation",{encoding:"application/x-tex"},"\\xi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")])])]),a(" とその時間微分 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"ξ"),s("mo",null,"˙")])]),s("annotation",{encoding:"application/x-tex"},"\\dot{\\xi}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1257em","vertical-align":"-0.1944em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")]),s("span",{style:{top:"-3.2634em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.0278em"}},[s("span",{class:"mord"},"˙")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])])])])]),a(" で表され,ポテンシャルエネルギーが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mi",null,"U"),s("mo",{stretchy:"false"},"("),s("mi",null,"ξ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"U=U(\\xi)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"mclose"},")")])])]),a(", 運動エネルギーが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"K"),s("mo",null,"="),s("mi",null,"μ"),s("msup",null,[s("mi",null,"ξ"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")]),s("annotation",{encoding:"application/x-tex"},"K=\\mu \\xi^2 / 2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/2")])])]),a(" であるならば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"μ"),s("mover",{accent:"true"},[s("mi",null,"ξ"),s("mo",null,"¨")]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\mu \\ddot{\\xi}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1257em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")]),s("span",{style:{top:"-3.2634em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1389em"}},[s("span",{class:"mord"},"¨")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"−"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"U"),s("mo",{stretchy:"false"},"("),s("mi",null,"ξ"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"ξ")]),s("annotation",{encoding:"application/x-tex"},"-\\mathrm{d} U(\\xi) / \\mathrm{d} \\xi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")])])]),a(". (したがって並進運動では, 力はポテン シャルエネルギーの微分)")])],-1),x=s("h3",{id:"_4-5-系質点",tabindex:"-1"},[a("4.5: 系質点 "),s("a",{class:"header-anchor",href:"#_4-5-系質点","aria-label":'Permalink to "4.5: 系質点"'},"​")],-1),w=s("ol",{start:"5"},[s("li",null,[a("系が質点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"m"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"m_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" で構成されているとき:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"c")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mi",{mathvariant:"normal"},"/"),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"j")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"P"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"i")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"bold-italic"},"L"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"i")]),s("mo",{separator:"true"},","),s("mi",null,"K"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"i"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",null,"I"),s("mi",null,"z")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msubsup",null,[s("mi",null,"x"),s("mi",null,"i"),s("mn",null,"2")]),s("mo",null,"+"),s("msubsup",null,[s("mi",null,"y"),s("mi",null,"i"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"∫"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"y"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"m")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\boldsymbol{r}_c=\\sum m_i \\boldsymbol{r}_i / \\sum m_j, \\boldsymbol{P}=\\sum m_i \\boldsymbol{v}_i \\\\ & \\boldsymbol{L}=\\sum m_i \\boldsymbol{r}_i \\times \\boldsymbol{v}_i, K=\\sum m_i v_i^2 / 2 \\\\ & I_z=\\sum m_i\\left(x_i^2+y_i^2\\right)=\\int\\left(x^2+y^2\\right) \\mathrm{d} m \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"7.8223em","vertical-align":"-3.6611em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1611em"}},[s("span",{style:{top:"-6.4711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.5711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.3611em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-0.3589em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6611em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1611em"}},[s("span",{style:{top:"-6.4711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-4.5711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/2")])]),s("span",{style:{top:"-2.3611em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-0.3589em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"})])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6611em"}},[s("span")])])])])])])])])])])])])],-1),z=s("h3",{id:"_4-6-質量中心の速度",tabindex:"-1"},[a("4.6: 質量中心の速度 "),s("a",{class:"header-anchor",href:"#_4-6-質量中心の速度","aria-label":'Permalink to "4.6: 質量中心の速度"'},"​")],-1),k=s("ol",{start:"6"},[s("li",null,[a("質量中心の速度が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" であるような系 (添え字 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(" は質量 中心についての物理量であることを示す):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"L"),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"L"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"R"),s("mi",null,"c")]),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")]),s("mo",{separator:"true"},","),s("mi",null,"K"),s("mo",null,"="),s("msub",null,[s("mi",null,"K"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"c"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"P"),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"P"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},".")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{L}=\\boldsymbol{L}_c+M_{\\Sigma} \\boldsymbol{R}_c \\times \\boldsymbol{v}_c, K=K_c+M_{\\Sigma} v_c^2 / 2 \\\\ \\boldsymbol{P}=\\boldsymbol{P}_c+M_{\\Sigma} \\boldsymbol{v}_c . \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.8979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.00421em"}},"R")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/2")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},".")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),_=s("h3",{id:"_4-7-steiner-定理",tabindex:"-1"},[a("4.7: Steiner 定理 "),s("a",{class:"header-anchor",href:"#_4-7-steiner-定理","aria-label":'Permalink to "4.7: Steiner 定理"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("Steiner の定理(平行軸の定理)も同じような形で は質量中心の回転軸からの距離):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"="),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mo",null,"+"),s("mi",null,"m"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"I=I_c+m b^2 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8641em"}}),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])])])],-1),f=s("h3",{id:"_4-8-ポイント-6",tabindex:"-1"},[a("4.8: ポイント 6 "),s("a",{class:"header-anchor",href:"#_4-8-ポイント-6","aria-label":'Permalink to "4.8: ポイント 6"'},"​")],-1),L=s("ol",{start:"8"},[s("li",null,[a("ポイント 6 の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"P")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{P}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"L")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])])])])]),a(" を用いて, Newton の第二法則 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"P"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"L"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}_{\\Sigma}=\\mathrm{d} \\boldsymbol{P} / \\mathrm{d} t, \\boldsymbol{M}_{\\Sigma}=\\mathrm{d} \\boldsymbol{L} / \\mathrm{d} t ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8361em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])])])])])])],-1),P=s("h3",{id:"_4-9-ポイント-5",tabindex:"-1"},[a("4.9: ポイント 5 "),s("a",{class:"header-anchor",href:"#_4-9-ポイント-5","aria-label":'Permalink to "4.9: ポイント 5"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("ポイント 5 にに加えて,質量中心を通る "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"z")]),s("annotation",{encoding:"application/x-tex"},"z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")])])]),a(" 軸に対する慣性モ一メントは "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mrow",null,[s("mi",null,"z"),s("mn",null,"0")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"I_{z 0}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",{separator:"true"},","),s("mi",null,"j")])]),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"m"),s("mi",null,"j")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mi",null,"j")]),s("mo",{fence:"true"},")")]),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"y"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"y"),s("mi",null,"j")]),s("mo",{fence:"true"},")")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"2"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"\\sum_{i, j} m_i m_j\\left[\\left(x_i-x_j\\right)^2+\\left(y_i-y_j\\right)^2\\right] /\\left(2 M_{\\Sigma}\\right)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.8em","vertical-align":"-0.65em"}}),s("span",{class:"mop"},[s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.162em"}},[s("span",{style:{top:"-2.4003em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4358em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size2"},"[")]),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size2"},"]")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])],-1),F=s("h3",{id:"_4-10-原点に対する慣性",tabindex:"-1"},[a("4.10: 原点に対する慣性 "),s("a",{class:"header-anchor",href:"#_4-10-原点に対する慣性","aria-label":'Permalink to "4.10: 原点に対する慣性"'},"​")],-1),T=s("ol",{start:"10"},[s("li",null,[a("原点に対する慣性モ一メント "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"θ"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msubsup",null,[s("mi",null,"r"),s("mi",null,"i"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\theta=\\sum m_i r_i^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0728em","vertical-align":"-0.2587em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-2.4413em","margin-left":"-0.0278em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2587em"}},[s("span")])])])])])])])]),a(" は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"θ"),s("mo",null,"="),s("msub",null,[s("mi",null,"I"),s("mi",null,"x")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"y")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"z")])]),s("annotation",{encoding:"application/x-tex"},"2 \\theta=I_x+I_y+I_z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9694em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" を用いることで二次元物体や等 方性のある物体の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mi",null,"z")])]),s("annotation",{encoding:"application/x-tex"},"I_z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" を計算するのに有用.")])],-1),S=s("h3",{id:"_4-11-相当単振子の長",tabindex:"-1"},[a("4.11: 相当単振子の長 "),s("a",{class:"header-anchor",href:"#_4-11-相当単振子の長","aria-label":'Permalink to "4.11: 相当単振子の長"'},"​")],-1),j=s("ol",{start:"11"},[s("li",null,[a("相当単振子の長さが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")])]),s("annotation",{encoding:"application/x-tex"},"\\tilde{l}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9313em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])])])])]),a(" である物理振子 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"ω"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"g"),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"l"),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m"),s("mi",null,"l"),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"ω"),s("mo",{stretchy:"false"},"("),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"ω"),s("mo",{stretchy:"false"},"("),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")]),s("mo",null,"−"),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("msqrt",null,[s("mrow",null,[s("mi",null,"g"),s("mi",{mathvariant:"normal"},"/"),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")])])]),s("mo",{separator:"true"},","),s("mspace",{width:"1em"}),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")]),s("mo",null,"="),s("mi",null,"l"),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m"),s("mi",null,"l")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\omega^2(l)=g /\\left(l+I_c / m l\\right) \\\\ & \\omega(l)=\\omega(\\tilde{l}-l)=\\sqrt{g / \\tilde{l}}, \\quad \\tilde{l}=l+I_c / m l \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"5.1641em","vertical-align":"-2.3321em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.8321em"}},[s("span",{style:{top:"-5.3425em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-3.3079em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.7025em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3321em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.8321em"}},[s("span",{style:{top:"-5.3425em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])]),s("span",{style:{top:"-3.3079em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mopen"},"("),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3745em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"/"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])])])]),s("span",{style:{top:"-3.3345em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as l,k as s,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const bs=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 4","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/4.md","filePath":"academic/physics/ipho-formulas-jpn/4.md","lastUpdated":1699051935000}'),h={name:"academic/physics/ipho-formulas-jpn/4.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-4",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 4 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-4","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 4"'},"​")],-1),g=n("",4),u=s("ol",{start:"2"},[s("li",null,[a("垂直抗力と摩擦力は 1 つの力に合成でき, 垂直抗力に 対して "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"arctan"),s("mo",null,"⁡"),s("mi",null,"μ")]),s("annotation",{encoding:"application/x-tex"},"\\arctan \\mu")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),s("span",{class:"mop"},"arctan"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"μ")])])]),a(" の角度で接触点に加わる.")])],-1),d=s("h3",{id:"_4-3-並進運動と回転運動",tabindex:"-1"},[a("4.3: 並進運動と回転運動 "),s("a",{class:"header-anchor",href:"#_4-3-並進運動と回転運動","aria-label":'Permalink to "4.3: 並進運動と回転運動"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("並進運動と回転運動についての Newton の第二法則:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",null,"m"),s("mi",{mathvariant:"bold-italic"},"a"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"M"),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"bold-italic"},"ε"),s("mspace",{width:"1em"}),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"M"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"F"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}=m \\boldsymbol{a}, \\boldsymbol{M}=I \\boldsymbol{\\varepsilon} \\quad(\\boldsymbol{M}=\\boldsymbol{r} \\times \\boldsymbol{F}) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8805em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"a")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"ε")])]),s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mclose"},")")])])])])]),a(" 二次元の場合には "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"M")]),s("annotation",{encoding:"application/x-tex"},"M")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ε")]),s("annotation",{encoding:"application/x-tex"},"\\varepsilon")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"ε")])])]),a(" は本質的にスカラーで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"M"),s("mo",null,"="),s("mi",null,"F"),s("mi",null,"l"),s("mo",null,"="),s("msub",null,[s("mi",null,"F"),s("mi",null,"t")]),s("mi",null,"r"),s("mo",{stretchy:"false"},"("),s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"M=F l=F_t r(l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"Fl"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2806em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1389em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"t")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(" は力のうでの長さ "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])])])],-1),v=s("h3",{id:"_4-4-一般化座標",tabindex:"-1"},[a("4.4: 一般化座標 "),s("a",{class:"header-anchor",href:"#_4-4-一般化座標","aria-label":'Permalink to "4.4: 一般化座標"'},"​")],-1),b=s("ol",{start:"4"},[s("li",null,[a("一般化座標. 系の状態が 1 つの変数 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ξ")]),s("annotation",{encoding:"application/x-tex"},"\\xi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")])])]),a(" とその時間微分 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"ξ"),s("mo",null,"˙")])]),s("annotation",{encoding:"application/x-tex"},"\\dot{\\xi}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1257em","vertical-align":"-0.1944em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")]),s("span",{style:{top:"-3.2634em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.0278em"}},[s("span",{class:"mord"},"˙")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])])])])]),a(" で表され,ポテンシャルエネルギーが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mi",null,"U"),s("mo",{stretchy:"false"},"("),s("mi",null,"ξ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"U=U(\\xi)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"mclose"},")")])])]),a(", 運動エネルギーが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"K"),s("mo",null,"="),s("mi",null,"μ"),s("msup",null,[s("mi",null,"ξ"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")]),s("annotation",{encoding:"application/x-tex"},"K=\\mu \\xi^2 / 2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/2")])])]),a(" であるならば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"μ"),s("mover",{accent:"true"},[s("mi",null,"ξ"),s("mo",null,"¨")]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\mu \\ddot{\\xi}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1257em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")]),s("span",{style:{top:"-3.2634em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1389em"}},[s("span",{class:"mord"},"¨")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"−"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"U"),s("mo",{stretchy:"false"},"("),s("mi",null,"ξ"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"ξ")]),s("annotation",{encoding:"application/x-tex"},"-\\mathrm{d} U(\\xi) / \\mathrm{d} \\xi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04601em"}},"ξ")])])]),a(". (したがって並進運動では, 力はポテン シャルエネルギーの微分)")])],-1),x=s("h3",{id:"_4-5-系質点",tabindex:"-1"},[a("4.5: 系質点 "),s("a",{class:"header-anchor",href:"#_4-5-系質点","aria-label":'Permalink to "4.5: 系質点"'},"​")],-1),w=s("ol",{start:"5"},[s("li",null,[a("系が質点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"m"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"m_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" で構成されているとき:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"c")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mi",{mathvariant:"normal"},"/"),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"j")]),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"P"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"i")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",{mathvariant:"bold-italic"},"L"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"i")]),s("mo",{separator:"true"},","),s("mi",null,"K"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"i"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msub",null,[s("mi",null,"I"),s("mi",null,"z")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("msubsup",null,[s("mi",null,"x"),s("mi",null,"i"),s("mn",null,"2")]),s("mo",null,"+"),s("msubsup",null,[s("mi",null,"y"),s("mi",null,"i"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mo",null,"∫"),s("mrow",null,[s("mo",{fence:"true"},"("),s("msup",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mi",null,"y"),s("mn",null,"2")]),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"m")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\boldsymbol{r}_c=\\sum m_i \\boldsymbol{r}_i / \\sum m_j, \\boldsymbol{P}=\\sum m_i \\boldsymbol{v}_i \\\\ & \\boldsymbol{L}=\\sum m_i \\boldsymbol{r}_i \\times \\boldsymbol{v}_i, K=\\sum m_i v_i^2 / 2 \\\\ & I_z=\\sum m_i\\left(x_i^2+y_i^2\\right)=\\int\\left(x^2+y^2\\right) \\mathrm{d} m \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"7.8223em","vertical-align":"-3.6611em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1611em"}},[s("span",{style:{top:"-6.4711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-4.5711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-2.3611em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-0.3589em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6611em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"4.1611em"}},[s("span",{style:{top:"-6.4711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-4.5711em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/2")])]),s("span",{style:{top:"-2.3611em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"m")])]),s("span",{style:{top:"-0.3589em"}},[s("span",{class:"pstrut",style:{height:"3.36em"}}),s("span",{class:"mord"},[s("span",{class:"mord"})])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"3.6611em"}},[s("span")])])])])])])])])])])])])],-1),z=s("h3",{id:"_4-6-質量中心の速度",tabindex:"-1"},[a("4.6: 質量中心の速度 "),s("a",{class:"header-anchor",href:"#_4-6-質量中心の速度","aria-label":'Permalink to "4.6: 質量中心の速度"'},"​")],-1),k=s("ol",{start:"6"},[s("li",null,[a("質量中心の速度が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")])]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{v}_c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" であるような系 (添え字 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"c")]),s("annotation",{encoding:"application/x-tex"},"c")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"c")])])]),a(" は質量 中心についての物理量であることを示す):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"L"),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"L"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"R"),s("mi",null,"c")]),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")]),s("mo",{separator:"true"},","),s("mi",null,"K"),s("mo",null,"="),s("msub",null,[s("mi",null,"K"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msubsup",null,[s("mi",null,"v"),s("mi",null,"c"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mn",null,"2")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"P"),s("mo",null,"="),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"P"),s("mi",null,"c")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"v"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},".")])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} \\boldsymbol{L}=\\boldsymbol{L}_c+M_{\\Sigma} \\boldsymbol{R}_c \\times \\boldsymbol{v}_c, K=K_c+M_{\\Sigma} v_c^2 / 2 \\\\ \\boldsymbol{P}=\\boldsymbol{P}_c+M_{\\Sigma} \\boldsymbol{v}_c . \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0241em","vertical-align":"-1.2621em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.7621em"}},[s("span",{style:{top:"-3.8979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.00421em"}},"R")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"K"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},"/2")])]),s("span",{style:{top:"-2.3979em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},".")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2621em"}},[s("span")])])])])])])])])])])])])],-1),_=s("h3",{id:"_4-7-steiner-定理",tabindex:"-1"},[a("4.7: Steiner 定理 "),s("a",{class:"header-anchor",href:"#_4-7-steiner-定理","aria-label":'Permalink to "4.7: Steiner 定理"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("Steiner の定理(平行軸の定理)も同じような形で は質量中心の回転軸からの距離):"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"="),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mo",null,"+"),s("mi",null,"m"),s("msup",null,[s("mi",null,"b"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"I=I_c+m b^2 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8641em"}}),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"b"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])])])],-1),f=s("h3",{id:"_4-8-ポイント-6",tabindex:"-1"},[a("4.8: ポイント 6 "),s("a",{class:"header-anchor",href:"#_4-8-ポイント-6","aria-label":'Permalink to "4.8: ポイント 6"'},"​")],-1),L=s("ol",{start:"8"},[s("li",null,[a("ポイント 6 の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"P")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{P}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"L")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{L}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])])])])]),a(" を用いて, Newton の第二法則 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"P"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"L"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"t")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}_{\\Sigma}=\\mathrm{d} \\boldsymbol{P} / \\mathrm{d} t, \\boldsymbol{M}_{\\Sigma}=\\mathrm{d} \\boldsymbol{L} / \\mathrm{d} t ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8361em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"P")])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.11424em"}},"M")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"L")])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord mathnormal"},"t")])])])])])])],-1),P=s("h3",{id:"_4-9-ポイント-5",tabindex:"-1"},[a("4.9: ポイント 5 "),s("a",{class:"header-anchor",href:"#_4-9-ポイント-5","aria-label":'Permalink to "4.9: ポイント 5"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("ポイント 5 にに加えて,質量中心を通る "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"z")]),s("annotation",{encoding:"application/x-tex"},"z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z")])])]),a(" 軸に対する慣性モ一メントは "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mrow",null,[s("mi",null,"z"),s("mn",null,"0")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"I_{z 0}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mord mtight"},"0")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",{separator:"true"},","),s("mi",null,"j")])]),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"m"),s("mi",null,"j")]),s("mrow",null,[s("mo",{fence:"true"},"["),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"x"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mi",null,"j")]),s("mo",{fence:"true"},")")]),s("mn",null,"2")]),s("mo",null,"+"),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",null,"y"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"y"),s("mi",null,"j")]),s("mo",{fence:"true"},")")]),s("mn",null,"2")]),s("mo",{fence:"true"},"]")]),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mn",null,"2"),s("msub",null,[s("mi",null,"M"),s("mi",{mathvariant:"normal"},"Σ")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"\\sum_{i, j} m_i m_j\\left[\\left(x_i-x_j\\right)^2+\\left(y_i-y_j\\right)^2\\right] /\\left(2 M_{\\Sigma}\\right)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.8em","vertical-align":"-0.65em"}}),s("span",{class:"mop"},[s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.162em"}},[s("span",{style:{top:"-2.4003em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mpunct mtight"},","),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4358em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size2"},"[")]),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size2"},"]")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"M"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.109em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])])])])],-1),F=s("h3",{id:"_4-10-原点に対する慣性",tabindex:"-1"},[a("4.10: 原点に対する慣性 "),s("a",{class:"header-anchor",href:"#_4-10-原点に対する慣性","aria-label":'Permalink to "4.10: 原点に対する慣性"'},"​")],-1),T=s("ol",{start:"10"},[s("li",null,[a("原点に対する慣性モ一メント "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"θ"),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"m"),s("mi",null,"i")]),s("msubsup",null,[s("mi",null,"r"),s("mi",null,"i"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\theta=\\sum m_i r_i^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0728em","vertical-align":"-0.2587em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"m"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-2.4413em","margin-left":"-0.0278em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2587em"}},[s("span")])])])])])])])]),a(" は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"θ"),s("mo",null,"="),s("msub",null,[s("mi",null,"I"),s("mi",null,"x")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"y")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"z")])]),s("annotation",{encoding:"application/x-tex"},"2 \\theta=I_x+I_y+I_z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9694em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" を用いることで二次元物体や等 方性のある物体の "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mi",null,"z")])]),s("annotation",{encoding:"application/x-tex"},"I_z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.04398em"}},"z")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" を計算するのに有用.")])],-1),S=s("h3",{id:"_4-11-相当単振子の長",tabindex:"-1"},[a("4.11: 相当単振子の長 "),s("a",{class:"header-anchor",href:"#_4-11-相当単振子の長","aria-label":'Permalink to "4.11: 相当単振子の長"'},"​")],-1),j=s("ol",{start:"11"},[s("li",null,[a("相当単振子の長さが "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")])]),s("annotation",{encoding:"application/x-tex"},"\\tilde{l}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9313em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])])])])]),a(" である物理振子 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("msup",null,[s("mi",null,"ω"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"g"),s("mi",{mathvariant:"normal"},"/"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"l"),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m"),s("mi",null,"l"),s("mo",{fence:"true"},")")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mrow"),s("mi",null,"ω"),s("mo",{stretchy:"false"},"("),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mi",null,"ω"),s("mo",{stretchy:"false"},"("),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")]),s("mo",null,"−"),s("mi",null,"l"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("msqrt",null,[s("mrow",null,[s("mi",null,"g"),s("mi",{mathvariant:"normal"},"/"),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")])])]),s("mo",{separator:"true"},","),s("mspace",{width:"1em"}),s("mover",{accent:"true"},[s("mi",null,"l"),s("mo",null,"~")]),s("mo",null,"="),s("mi",null,"l"),s("mo",null,"+"),s("msub",null,[s("mi",null,"I"),s("mi",null,"c")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"m"),s("mi",null,"l")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])]),s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow")])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{aligned} & \\omega^2(l)=g /\\left(l+I_c / m l\\right) \\\\ & \\omega(l)=\\omega(\\tilde{l}-l)=\\sqrt{g / \\tilde{l}}, \\quad \\tilde{l}=l+I_c / m l \\\\ & \\end{aligned} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"5.1641em","vertical-align":"-2.3321em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-r"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.8321em"}},[s("span",{style:{top:"-5.3425em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-3.3079em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})]),s("span",{style:{top:"-1.7025em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"})])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.3321em"}},[s("span")])])])]),s("span",{class:"col-align-l"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.8321em"}},[s("span",{style:{top:"-5.3425em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"c")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"m"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")])])]),s("span",{style:{top:"-3.3079em"}},[s("span",{class:"pstrut",style:{height:"3.3745em"}}),s("span",{class:"mord"},[s("span",{class:"mord"}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mopen"},"("),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3745em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"mord"},"/"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9313em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")]),s("span",{style:{top:"-3.6134em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1667em"}},[s("span",{class:"mord"},"~")])])])])])])])]),s("span",{style:{top:"-3.3345em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 l0 -0 c4,-6.7,10,-10,18,-10 H400000v40 H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7 diff --git a/assets/academic_physics_ipho-formulas-jpn_5.md.6c32aa10.js b/assets/academic_physics_ipho-formulas-jpn_5.md.948cb5df.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_5.md.6c32aa10.js rename to assets/academic_physics_ipho-formulas-jpn_5.md.948cb5df.js index fa0d99b4..3552d6ca 100644 --- a/assets/academic_physics_ipho-formulas-jpn_5.md.6c32aa10.js +++ b/assets/academic_physics_ipho-formulas-jpn_5.md.948cb5df.js @@ -1,4 +1,4 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const I=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 5","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/5.md","filePath":"academic/physics/ipho-formulas-jpn/5.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/5.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-5",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 5 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-5","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 5"'},"​")],-1),r=s("h2",{id:"_5-振動と波",tabindex:"-1"},[a("5. 振動と波 "),s("a",{class:"header-anchor",href:"#_5-振動と波","aria-label":'Permalink to "5. 振動と波"'},"​")],-1),h=s("h3",{id:"_5-1-減衰振動",tabindex:"-1"},[a("5.1: 減衰振動 "),s("a",{class:"header-anchor",href:"#_5-1-減衰振動","aria-label":'Permalink to "5.1: 減衰振動"'},"​")],-1),g=s("ol",null,[s("li",null,[a("減衰振動:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"x"),s("mo",null,"¨")]),s("mo",null,"+"),s("mn",null,"2"),s("mi",null,"γ"),s("mover",{accent:"true"},[s("mi",null,"x"),s("mo",null,"˙")]),s("mo",null,"+"),s("msubsup",null,[s("mi",null,"ω"),s("mn",null,"0"),s("mn",null,"2")]),s("mi",null,"x"),s("mo",null,"="),s("mn",null,"0"),s("mo",{stretchy:"false"},"("),s("mi",null,"γ"),s("mo",null,"<"),s("mi",null,"ω"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\ddot{x}+2 \\gamma \\dot{x}+\\omega_0^2 x=0(\\gamma<\\omega) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7512em","vertical-align":"-0.0833em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"x")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.2222em"}},[s("span",{class:"mord"},"¨")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8623em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"x")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1111em"}},[s("span",{class:"mord"},"˙")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1111em","vertical-align":"-0.247em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"<"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")")])])])])]),a(" この方程式の解は ((Section 1: #3)[1#_1-3-定数係数線形微分方程式] 参照) :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"γ"),s("mi",null,"t")])]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"t"),s("msqrt",null,[s("mrow",null,[s("msubsup",null,[s("mi",null,"ω"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",null,"−"),s("msup",null,[s("mi",null,"γ"),s("mn",null,"2")])])]),s("mo",null,"−"),s("msub",null,[s("mi",null,"φ"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"x=x_0 e^{-\\gamma t} \\sin \\left(t \\sqrt{\\omega_0^2-\\gamma^2}-\\varphi_0\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8436em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord mathnormal mtight"},"t")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2987em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7959em"}},[s("span",{style:{top:"-2.4337em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.0448em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2663em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.2587em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const I=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 5","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/5.md","filePath":"academic/physics/ipho-formulas-jpn/5.md","lastUpdated":1699051935000}'),p={name:"academic/physics/ipho-formulas-jpn/5.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-5",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 5 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-5","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 5"'},"​")],-1),r=s("h2",{id:"_5-振動と波",tabindex:"-1"},[a("5. 振動と波 "),s("a",{class:"header-anchor",href:"#_5-振動と波","aria-label":'Permalink to "5. 振動と波"'},"​")],-1),h=s("h3",{id:"_5-1-減衰振動",tabindex:"-1"},[a("5.1: 減衰振動 "),s("a",{class:"header-anchor",href:"#_5-1-減衰振動","aria-label":'Permalink to "5.1: 減衰振動"'},"​")],-1),g=s("ol",null,[s("li",null,[a("減衰振動:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"x"),s("mo",null,"¨")]),s("mo",null,"+"),s("mn",null,"2"),s("mi",null,"γ"),s("mover",{accent:"true"},[s("mi",null,"x"),s("mo",null,"˙")]),s("mo",null,"+"),s("msubsup",null,[s("mi",null,"ω"),s("mn",null,"0"),s("mn",null,"2")]),s("mi",null,"x"),s("mo",null,"="),s("mn",null,"0"),s("mo",{stretchy:"false"},"("),s("mi",null,"γ"),s("mo",null,"<"),s("mi",null,"ω"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\ddot{x}+2 \\gamma \\dot{x}+\\omega_0^2 x=0(\\gamma<\\omega) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7512em","vertical-align":"-0.0833em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"x")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.2222em"}},[s("span",{class:"mord"},"¨")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8623em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"x")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1111em"}},[s("span",{class:"mord"},"˙")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1111em","vertical-align":"-0.247em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"<"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")")])])])])]),a(" この方程式の解は ((Section 1: #3)[1#_1-3-定数係数線形微分方程式] 参照) :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"γ"),s("mi",null,"t")])]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"t"),s("msqrt",null,[s("mrow",null,[s("msubsup",null,[s("mi",null,"ω"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",null,"−"),s("msup",null,[s("mi",null,"γ"),s("mn",null,"2")])])]),s("mo",null,"−"),s("msub",null,[s("mi",null,"φ"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"x=x_0 e^{-\\gamma t} \\sin \\left(t \\sqrt{\\omega_0^2-\\gamma^2}-\\varphi_0\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8436em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord mathnormal mtight"},"t")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2987em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7959em"}},[s("span",{style:{top:"-2.4337em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.0448em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2663em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.2587em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 l0 -0 c4,-6.7,10,-10,18,-10 H400000v40 H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7 diff --git a/assets/academic_physics_ipho-formulas-jpn_5.md.6c32aa10.lean.js b/assets/academic_physics_ipho-formulas-jpn_5.md.948cb5df.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_5.md.6c32aa10.lean.js rename to assets/academic_physics_ipho-formulas-jpn_5.md.948cb5df.lean.js index fa0d99b4..3552d6ca 100644 --- a/assets/academic_physics_ipho-formulas-jpn_5.md.6c32aa10.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_5.md.948cb5df.lean.js @@ -1,4 +1,4 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const I=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 5","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/5.md","filePath":"academic/physics/ipho-formulas-jpn/5.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/5.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-5",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 5 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-5","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 5"'},"​")],-1),r=s("h2",{id:"_5-振動と波",tabindex:"-1"},[a("5. 振動と波 "),s("a",{class:"header-anchor",href:"#_5-振動と波","aria-label":'Permalink to "5. 振動と波"'},"​")],-1),h=s("h3",{id:"_5-1-減衰振動",tabindex:"-1"},[a("5.1: 減衰振動 "),s("a",{class:"header-anchor",href:"#_5-1-減衰振動","aria-label":'Permalink to "5.1: 減衰振動"'},"​")],-1),g=s("ol",null,[s("li",null,[a("減衰振動:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"x"),s("mo",null,"¨")]),s("mo",null,"+"),s("mn",null,"2"),s("mi",null,"γ"),s("mover",{accent:"true"},[s("mi",null,"x"),s("mo",null,"˙")]),s("mo",null,"+"),s("msubsup",null,[s("mi",null,"ω"),s("mn",null,"0"),s("mn",null,"2")]),s("mi",null,"x"),s("mo",null,"="),s("mn",null,"0"),s("mo",{stretchy:"false"},"("),s("mi",null,"γ"),s("mo",null,"<"),s("mi",null,"ω"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\ddot{x}+2 \\gamma \\dot{x}+\\omega_0^2 x=0(\\gamma<\\omega) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7512em","vertical-align":"-0.0833em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"x")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.2222em"}},[s("span",{class:"mord"},"¨")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8623em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"x")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1111em"}},[s("span",{class:"mord"},"˙")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1111em","vertical-align":"-0.247em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"<"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")")])])])])]),a(" この方程式の解は ((Section 1: #3)[1#_1-3-定数係数線形微分方程式] 参照) :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"γ"),s("mi",null,"t")])]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"t"),s("msqrt",null,[s("mrow",null,[s("msubsup",null,[s("mi",null,"ω"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",null,"−"),s("msup",null,[s("mi",null,"γ"),s("mn",null,"2")])])]),s("mo",null,"−"),s("msub",null,[s("mi",null,"φ"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"x=x_0 e^{-\\gamma t} \\sin \\left(t \\sqrt{\\omega_0^2-\\gamma^2}-\\varphi_0\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8436em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord mathnormal mtight"},"t")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2987em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7959em"}},[s("span",{style:{top:"-2.4337em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.0448em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2663em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.2587em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const I=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 5","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/5.md","filePath":"academic/physics/ipho-formulas-jpn/5.md","lastUpdated":1699051935000}'),p={name:"academic/physics/ipho-formulas-jpn/5.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-5",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 5 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-5","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 5"'},"​")],-1),r=s("h2",{id:"_5-振動と波",tabindex:"-1"},[a("5. 振動と波 "),s("a",{class:"header-anchor",href:"#_5-振動と波","aria-label":'Permalink to "5. 振動と波"'},"​")],-1),h=s("h3",{id:"_5-1-減衰振動",tabindex:"-1"},[a("5.1: 減衰振動 "),s("a",{class:"header-anchor",href:"#_5-1-減衰振動","aria-label":'Permalink to "5.1: 減衰振動"'},"​")],-1),g=s("ol",null,[s("li",null,[a("減衰振動:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"x"),s("mo",null,"¨")]),s("mo",null,"+"),s("mn",null,"2"),s("mi",null,"γ"),s("mover",{accent:"true"},[s("mi",null,"x"),s("mo",null,"˙")]),s("mo",null,"+"),s("msubsup",null,[s("mi",null,"ω"),s("mn",null,"0"),s("mn",null,"2")]),s("mi",null,"x"),s("mo",null,"="),s("mn",null,"0"),s("mo",{stretchy:"false"},"("),s("mi",null,"γ"),s("mo",null,"<"),s("mi",null,"ω"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\ddot{x}+2 \\gamma \\dot{x}+\\omega_0^2 x=0(\\gamma<\\omega) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7512em","vertical-align":"-0.0833em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"x")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.2222em"}},[s("span",{class:"mord"},"¨")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8623em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"x")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1111em"}},[s("span",{class:"mord"},"˙")])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1111em","vertical-align":"-0.247em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"<"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")")])])])])]),a(" この方程式の解は ((Section 1: #3)[1#_1-3-定数係数線形微分方程式] 参照) :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("msub",null,[s("mi",null,"x"),s("mn",null,"0")]),s("msup",null,[s("mi",null,"e"),s("mrow",null,[s("mo",null,"−"),s("mi",null,"γ"),s("mi",null,"t")])]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"t"),s("msqrt",null,[s("mrow",null,[s("msubsup",null,[s("mi",null,"ω"),s("mn",null,"0"),s("mn",null,"2")]),s("mo",null,"−"),s("msup",null,[s("mi",null,"γ"),s("mn",null,"2")])])]),s("mo",null,"−"),s("msub",null,[s("mi",null,"φ"),s("mn",null,"0")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"x=x_0 e^{-\\gamma t} \\sin \\left(t \\sqrt{\\omega_0^2-\\gamma^2}-\\varphi_0\\right) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"e"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8436em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"mord mathnormal mtight"},"t")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2987em"}},[s("span",{class:"svg-align",style:{top:"-3.8em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7959em"}},[s("span",{style:{top:"-2.4337em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"0")])]),s("span",{style:{top:"-3.0448em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2663em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05556em"}},"γ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.2587em"}},[s("span",{class:"pstrut",style:{height:"3.8em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.88em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.88em",viewBox:"0 0 400000 1944",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M983 90 l0 -0 c4,-6.7,10,-10,18,-10 H400000v40 H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7 diff --git a/assets/academic_physics_ipho-formulas-jpn_6.md.bc519d11.js b/assets/academic_physics_ipho-formulas-jpn_6.md.d563d3f1.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_6.md.bc519d11.js rename to assets/academic_physics_ipho-formulas-jpn_6.md.d563d3f1.js index 8872b6a0..33e77b21 100644 --- a/assets/academic_physics_ipho-formulas-jpn_6.md.bc519d11.js +++ b/assets/academic_physics_ipho-formulas-jpn_6.md.d563d3f1.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as m,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 6","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/6.md","filePath":"academic/physics/ipho-formulas-jpn/6.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/6.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-6",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 6 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-6","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 6"'},"​")],-1),h=s("h2",{id:"_6-幾何光学-測光",tabindex:"-1"},[a("6: 幾何光学,測光 "),s("a",{class:"header-anchor",href:"#_6-幾何光学-測光","aria-label":'Permalink to "6: 幾何光学,測光"'},"​")],-1),o=s("h3",{id:"_6-1-fermat-原理",tabindex:"-1"},[a("6.1: Fermat 原理 "),s("a",{class:"header-anchor",href:"#_6-1-fermat-原理","aria-label":'Permalink to "6.1: Fermat 原理"'},"​")],-1),g=s("ol",null,[s("li",null,[a("Fermat の原理 : 点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A")]),s("annotation",{encoding:"application/x-tex"},"A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A")])])]),a(" から "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" への波の経路は波の移動 時間が最も短いもの.")])],-1),u=s("h3",{id:"_6-2-snell-法則",tabindex:"-1"},[a("6.2: Snell 法則 "),s("a",{class:"header-anchor",href:"#_6-2-snell-法則","aria-label":'Permalink to "6.2: Snell 法則"'},"​")],-1),d=s("ol",{start:"2"},[s("li",null,"Snell の法則 :")],-1),y=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"α"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"α"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",null,"n"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"n"),s("mn",null,"1")]),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\sin \\alpha_1 / \\sin \\alpha_2=n_2 / n_1=v_1 / v_2 . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},".")])])])])],-1),x=s("h3",{id:"_6-3-屈折率",tabindex:"-1"},[a("6.3: 屈折率 "),s("a",{class:"header-anchor",href:"#_6-3-屈折率","aria-label":'Permalink to "6.3: 屈折率"'},"​")],-1),v=s("ol",{start:"3"},[s("li",null,[a("屈折率が連続的に変化するならば,媒質を屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n")])])]),a(" で一定のいくつかの仮想的な層に分けて Snell の 法則を適用する. 光線は屈折率一定の層に沿って進む こともでき,もし全反射の条件をわずかに満たせば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"n"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"n"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("mspace",{width:"1em"}),s("mo",{stretchy:"false"},"("),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"n^{\\prime}=n / r \\quad(r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" は曲率半径 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])])])],-1),w=s("h3",{id:"_6-4-屈折率な座標",tabindex:"-1"},[a("6.4: 屈折率な座標 "),s("a",{class:"header-anchor",href:"#_6-4-屈折率な座標","aria-label":'Permalink to "6.4: 屈折率な座標"'},"​")],-1),_=s("ol",{start:"4"},[s("li",null,[a("屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"z")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{z}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathrm"},"z")])])]),a(" 座標にのみ依存するならば, 光子の運動量 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"p"),s("mi",null,"y")])]),s("annotation",{encoding:"application/x-tex"},"p_x, p_y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7167em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(" とエネルギーは保存される:")])],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"k"),s("mi",null,"y")]),s("mo",null,"="),s("mtext",null," const., "),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"k"),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"n"),s("mo",null,"="),s("mtext",null," const. ")]),s("annotation",{encoding:"application/x-tex"},"k_x, k_y=\\text { const., }|\\boldsymbol{k}| / n=\\text { const. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const., ")]),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.01852em"}},"k")])]),s("span",{class:"mord"},"∣/"),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const. ")])])])])])],-1),k=s("h3",{id:"_6-5-薄いレンズの式",tabindex:"-1"},[a("6.5:薄いレンズの式 "),s("a",{class:"header-anchor",href:"#_6-5-薄いレンズの式","aria-label":'Permalink to "6.5:薄いレンズの式"'},"​")],-1),f=s("ol",{start:"6"},[s("li",null,"薄いレンズの式(符号に注意する):")],-1),M=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"a"),s("mo",null,"+"),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"b"),s("mo",null,"="),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"f"),s("mo",null,"≡"),s("mi",null,"D")]),s("annotation",{encoding:"application/x-tex"},"1 / a+1 / b=1 / f \\equiv D ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≡"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"D")])])])])],-1),z=s("h3",{id:"_6-6-newton-の式",tabindex:"-1"},[a("6.6: Newton の式 "),s("a",{class:"header-anchor",href:"#_6-6-newton-の式","aria-label":'Permalink to "6.6: Newton の式"'},"​")],-1),P=s("ol",{start:"6"},[s("li",null,[a("Newton の式 : 物体側焦点から物体までの距離を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},"x_1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(", 像側焦点から像までの距離を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"x_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" とすると, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"="),s("msup",null,[s("mi",null,"f"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"x_1 x_2=f^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])],-1),L=r('

    6.7: 像の位置を求める視差法

    1. 像の位置を求める視差法 : 目の位置と垂直に動かした ときに,鉛筆の先が像に対してずれないような位置を 探す.

    6.8: レンズを通る光線の経路の幾何学的な描き方

    1. レンズを通る光線の経路の幾何学的な描き方:a) レン ズの中心を通る光線は屈折しない。b) 光軸に平行な光 線は焦点を通る,c) 屈折後, 初めに平行だった光線どうしは焦点面(焦点を通り光軸に垂直な平面)上で集 まる.d) 平面の像は平面であり,この 2 つの平面はレ ンズの平面上で交わる.

    6.9: 光束

    ',5),I=s("ol",{start:"9"},[s("li",null,[a("光束 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ")]),s("annotation",{encoding:"application/x-tex"},"\\Phi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ")])])]),a(" [単位: lumen "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"lm"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(\\operatorname{lm})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"lm")]),s("span",{class:"mclose"},")")])])]),a("] は, 光のエネルギー を示し, 眼の感度に応じて重み付けされる. 光度 [candela (cd)]は(光源から出る)立体角あたりの 光束で, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"Ω")]),s("annotation",{encoding:"application/x-tex"},"I=\\Phi / \\Omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/Ω")])])]),a(". 照度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"lux"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"l"),s("mi",{mathvariant:"normal"},"x")]),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"[\\operatorname{lux}(\\mathrm{lx})]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"lux")]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"lx")]),s("span",{class:"mclose"},")]")])])]),a(" は(面に入射する) 面積あたりの光束で, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"S")]),s("annotation",{encoding:"application/x-tex"},"E=\\Phi / S")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S")])])]),a(".")])],-1),S=s("h3",{id:"_6-10-gauss-定理",tabindex:"-1"},[a("6.10: Gauss 定理 "),s("a",{class:"header-anchor",href:"#_6-10-gauss-定理","aria-label":'Permalink to "6.10: Gauss 定理"'},"​")],-1),N=s("ol",{start:"10"},[s("li",null,[a("光束についての Gauss の定理 : 光度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"I_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" の点光源を囲 む閉曲面を通って外に出る光束は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"="),s("mn",null,"4"),s("mi",null,"π"),s("mo",null,"∑"),s("msub",null,[s("mi",null,"I"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"\\Phi=4 \\pi \\sum I_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". 光 源が 1 つで距離が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" のとき "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"E=I / r^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])],-1),q=s("h3",{id:"_6-11-実験のヒント",tabindex:"-1"},[a("6.11: 実験のヒント "),s("a",{class:"header-anchor",href:"#_6-11-実験のヒント","aria-label":'Permalink to "6.11: 実験のヒント"'},"​")],-1),E=s("ol",{start:"11"},[s("li",null,"実験のヒント:紙についた油污れが周囲の紙と同じ明 るさならば,その紙は両面から同じように照らされて いる.")],-1);function T(A,B,F,V,D,O){const l=t;return e(),m("div",null,[c,i(l,{readTime:"1",words:"428"}),h,o,g,u,d,y,x,v,w,_,b,k,f,M,z,P,L,I,S,N,q,E])}const H=n(p,[["render",T]]);export{C as __pageData,H as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as m,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 6","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/6.md","filePath":"academic/physics/ipho-formulas-jpn/6.md","lastUpdated":1699051935000}'),p={name:"academic/physics/ipho-formulas-jpn/6.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-6",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 6 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-6","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 6"'},"​")],-1),h=s("h2",{id:"_6-幾何光学-測光",tabindex:"-1"},[a("6: 幾何光学,測光 "),s("a",{class:"header-anchor",href:"#_6-幾何光学-測光","aria-label":'Permalink to "6: 幾何光学,測光"'},"​")],-1),o=s("h3",{id:"_6-1-fermat-原理",tabindex:"-1"},[a("6.1: Fermat 原理 "),s("a",{class:"header-anchor",href:"#_6-1-fermat-原理","aria-label":'Permalink to "6.1: Fermat 原理"'},"​")],-1),g=s("ol",null,[s("li",null,[a("Fermat の原理 : 点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A")]),s("annotation",{encoding:"application/x-tex"},"A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A")])])]),a(" から "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" への波の経路は波の移動 時間が最も短いもの.")])],-1),u=s("h3",{id:"_6-2-snell-法則",tabindex:"-1"},[a("6.2: Snell 法則 "),s("a",{class:"header-anchor",href:"#_6-2-snell-法則","aria-label":'Permalink to "6.2: Snell 法則"'},"​")],-1),d=s("ol",{start:"2"},[s("li",null,"Snell の法則 :")],-1),y=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"α"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"α"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",null,"n"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"n"),s("mn",null,"1")]),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\sin \\alpha_1 / \\sin \\alpha_2=n_2 / n_1=v_1 / v_2 . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},".")])])])])],-1),x=s("h3",{id:"_6-3-屈折率",tabindex:"-1"},[a("6.3: 屈折率 "),s("a",{class:"header-anchor",href:"#_6-3-屈折率","aria-label":'Permalink to "6.3: 屈折率"'},"​")],-1),v=s("ol",{start:"3"},[s("li",null,[a("屈折率が連続的に変化するならば,媒質を屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n")])])]),a(" で一定のいくつかの仮想的な層に分けて Snell の 法則を適用する. 光線は屈折率一定の層に沿って進む こともでき,もし全反射の条件をわずかに満たせば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"n"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"n"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("mspace",{width:"1em"}),s("mo",{stretchy:"false"},"("),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"n^{\\prime}=n / r \\quad(r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" は曲率半径 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])])])],-1),w=s("h3",{id:"_6-4-屈折率な座標",tabindex:"-1"},[a("6.4: 屈折率な座標 "),s("a",{class:"header-anchor",href:"#_6-4-屈折率な座標","aria-label":'Permalink to "6.4: 屈折率な座標"'},"​")],-1),_=s("ol",{start:"4"},[s("li",null,[a("屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"z")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{z}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathrm"},"z")])])]),a(" 座標にのみ依存するならば, 光子の運動量 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"p"),s("mi",null,"y")])]),s("annotation",{encoding:"application/x-tex"},"p_x, p_y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7167em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(" とエネルギーは保存される:")])],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"k"),s("mi",null,"y")]),s("mo",null,"="),s("mtext",null," const., "),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"k"),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"n"),s("mo",null,"="),s("mtext",null," const. ")]),s("annotation",{encoding:"application/x-tex"},"k_x, k_y=\\text { const., }|\\boldsymbol{k}| / n=\\text { const. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const., ")]),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.01852em"}},"k")])]),s("span",{class:"mord"},"∣/"),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const. ")])])])])])],-1),k=s("h3",{id:"_6-5-薄いレンズの式",tabindex:"-1"},[a("6.5:薄いレンズの式 "),s("a",{class:"header-anchor",href:"#_6-5-薄いレンズの式","aria-label":'Permalink to "6.5:薄いレンズの式"'},"​")],-1),f=s("ol",{start:"6"},[s("li",null,"薄いレンズの式(符号に注意する):")],-1),M=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"a"),s("mo",null,"+"),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"b"),s("mo",null,"="),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"f"),s("mo",null,"≡"),s("mi",null,"D")]),s("annotation",{encoding:"application/x-tex"},"1 / a+1 / b=1 / f \\equiv D ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≡"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"D")])])])])],-1),z=s("h3",{id:"_6-6-newton-の式",tabindex:"-1"},[a("6.6: Newton の式 "),s("a",{class:"header-anchor",href:"#_6-6-newton-の式","aria-label":'Permalink to "6.6: Newton の式"'},"​")],-1),P=s("ol",{start:"6"},[s("li",null,[a("Newton の式 : 物体側焦点から物体までの距離を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},"x_1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(", 像側焦点から像までの距離を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"x_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" とすると, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"="),s("msup",null,[s("mi",null,"f"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"x_1 x_2=f^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])],-1),L=r('

    6.7: 像の位置を求める視差法

    1. 像の位置を求める視差法 : 目の位置と垂直に動かした ときに,鉛筆の先が像に対してずれないような位置を 探す.

    6.8: レンズを通る光線の経路の幾何学的な描き方

    1. レンズを通る光線の経路の幾何学的な描き方:a) レン ズの中心を通る光線は屈折しない。b) 光軸に平行な光 線は焦点を通る,c) 屈折後, 初めに平行だった光線どうしは焦点面(焦点を通り光軸に垂直な平面)上で集 まる.d) 平面の像は平面であり,この 2 つの平面はレ ンズの平面上で交わる.

    6.9: 光束

    ',5),I=s("ol",{start:"9"},[s("li",null,[a("光束 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ")]),s("annotation",{encoding:"application/x-tex"},"\\Phi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ")])])]),a(" [単位: lumen "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"lm"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(\\operatorname{lm})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"lm")]),s("span",{class:"mclose"},")")])])]),a("] は, 光のエネルギー を示し, 眼の感度に応じて重み付けされる. 光度 [candela (cd)]は(光源から出る)立体角あたりの 光束で, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"Ω")]),s("annotation",{encoding:"application/x-tex"},"I=\\Phi / \\Omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/Ω")])])]),a(". 照度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"lux"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"l"),s("mi",{mathvariant:"normal"},"x")]),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"[\\operatorname{lux}(\\mathrm{lx})]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"lux")]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"lx")]),s("span",{class:"mclose"},")]")])])]),a(" は(面に入射する) 面積あたりの光束で, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"S")]),s("annotation",{encoding:"application/x-tex"},"E=\\Phi / S")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S")])])]),a(".")])],-1),S=s("h3",{id:"_6-10-gauss-定理",tabindex:"-1"},[a("6.10: Gauss 定理 "),s("a",{class:"header-anchor",href:"#_6-10-gauss-定理","aria-label":'Permalink to "6.10: Gauss 定理"'},"​")],-1),N=s("ol",{start:"10"},[s("li",null,[a("光束についての Gauss の定理 : 光度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"I_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" の点光源を囲 む閉曲面を通って外に出る光束は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"="),s("mn",null,"4"),s("mi",null,"π"),s("mo",null,"∑"),s("msub",null,[s("mi",null,"I"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"\\Phi=4 \\pi \\sum I_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". 光 源が 1 つで距離が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" のとき "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"E=I / r^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])],-1),q=s("h3",{id:"_6-11-実験のヒント",tabindex:"-1"},[a("6.11: 実験のヒント "),s("a",{class:"header-anchor",href:"#_6-11-実験のヒント","aria-label":'Permalink to "6.11: 実験のヒント"'},"​")],-1),E=s("ol",{start:"11"},[s("li",null,"実験のヒント:紙についた油污れが周囲の紙と同じ明 るさならば,その紙は両面から同じように照らされて いる.")],-1);function T(A,B,F,V,D,O){const l=t;return e(),m("div",null,[c,i(l,{readTime:"1",words:"428"}),h,o,g,u,d,y,x,v,w,_,b,k,f,M,z,P,L,I,S,N,q,E])}const H=n(p,[["render",T]]);export{C as __pageData,H as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_6.md.bc519d11.lean.js b/assets/academic_physics_ipho-formulas-jpn_6.md.d563d3f1.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_6.md.bc519d11.lean.js rename to assets/academic_physics_ipho-formulas-jpn_6.md.d563d3f1.lean.js index 27e98367..155bf213 100644 --- a/assets/academic_physics_ipho-formulas-jpn_6.md.bc519d11.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_6.md.d563d3f1.lean.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as m,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 6","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/6.md","filePath":"academic/physics/ipho-formulas-jpn/6.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/6.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-6",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 6 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-6","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 6"'},"​")],-1),h=s("h2",{id:"_6-幾何光学-測光",tabindex:"-1"},[a("6: 幾何光学,測光 "),s("a",{class:"header-anchor",href:"#_6-幾何光学-測光","aria-label":'Permalink to "6: 幾何光学,測光"'},"​")],-1),o=s("h3",{id:"_6-1-fermat-原理",tabindex:"-1"},[a("6.1: Fermat 原理 "),s("a",{class:"header-anchor",href:"#_6-1-fermat-原理","aria-label":'Permalink to "6.1: Fermat 原理"'},"​")],-1),g=s("ol",null,[s("li",null,[a("Fermat の原理 : 点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A")]),s("annotation",{encoding:"application/x-tex"},"A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A")])])]),a(" から "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" への波の経路は波の移動 時間が最も短いもの.")])],-1),u=s("h3",{id:"_6-2-snell-法則",tabindex:"-1"},[a("6.2: Snell 法則 "),s("a",{class:"header-anchor",href:"#_6-2-snell-法則","aria-label":'Permalink to "6.2: Snell 法則"'},"​")],-1),d=s("ol",{start:"2"},[s("li",null,"Snell の法則 :")],-1),y=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"α"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"α"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",null,"n"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"n"),s("mn",null,"1")]),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\sin \\alpha_1 / \\sin \\alpha_2=n_2 / n_1=v_1 / v_2 . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},".")])])])])],-1),x=s("h3",{id:"_6-3-屈折率",tabindex:"-1"},[a("6.3: 屈折率 "),s("a",{class:"header-anchor",href:"#_6-3-屈折率","aria-label":'Permalink to "6.3: 屈折率"'},"​")],-1),v=s("ol",{start:"3"},[s("li",null,[a("屈折率が連続的に変化するならば,媒質を屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n")])])]),a(" で一定のいくつかの仮想的な層に分けて Snell の 法則を適用する. 光線は屈折率一定の層に沿って進む こともでき,もし全反射の条件をわずかに満たせば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"n"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"n"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("mspace",{width:"1em"}),s("mo",{stretchy:"false"},"("),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"n^{\\prime}=n / r \\quad(r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" は曲率半径 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])])])],-1),w=s("h3",{id:"_6-4-屈折率な座標",tabindex:"-1"},[a("6.4: 屈折率な座標 "),s("a",{class:"header-anchor",href:"#_6-4-屈折率な座標","aria-label":'Permalink to "6.4: 屈折率な座標"'},"​")],-1),_=s("ol",{start:"4"},[s("li",null,[a("屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"z")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{z}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathrm"},"z")])])]),a(" 座標にのみ依存するならば, 光子の運動量 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"p"),s("mi",null,"y")])]),s("annotation",{encoding:"application/x-tex"},"p_x, p_y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7167em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(" とエネルギーは保存される:")])],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"k"),s("mi",null,"y")]),s("mo",null,"="),s("mtext",null," const., "),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"k"),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"n"),s("mo",null,"="),s("mtext",null," const. ")]),s("annotation",{encoding:"application/x-tex"},"k_x, k_y=\\text { const., }|\\boldsymbol{k}| / n=\\text { const. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const., ")]),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.01852em"}},"k")])]),s("span",{class:"mord"},"∣/"),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const. ")])])])])])],-1),k=s("h3",{id:"_6-5-薄いレンズの式",tabindex:"-1"},[a("6.5:薄いレンズの式 "),s("a",{class:"header-anchor",href:"#_6-5-薄いレンズの式","aria-label":'Permalink to "6.5:薄いレンズの式"'},"​")],-1),f=s("ol",{start:"6"},[s("li",null,"薄いレンズの式(符号に注意する):")],-1),M=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"a"),s("mo",null,"+"),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"b"),s("mo",null,"="),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"f"),s("mo",null,"≡"),s("mi",null,"D")]),s("annotation",{encoding:"application/x-tex"},"1 / a+1 / b=1 / f \\equiv D ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≡"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"D")])])])])],-1),z=s("h3",{id:"_6-6-newton-の式",tabindex:"-1"},[a("6.6: Newton の式 "),s("a",{class:"header-anchor",href:"#_6-6-newton-の式","aria-label":'Permalink to "6.6: Newton の式"'},"​")],-1),P=s("ol",{start:"6"},[s("li",null,[a("Newton の式 : 物体側焦点から物体までの距離を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},"x_1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(", 像側焦点から像までの距離を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"x_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" とすると, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"="),s("msup",null,[s("mi",null,"f"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"x_1 x_2=f^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])],-1),L=r("",5),I=s("ol",{start:"9"},[s("li",null,[a("光束 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ")]),s("annotation",{encoding:"application/x-tex"},"\\Phi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ")])])]),a(" [単位: lumen "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"lm"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(\\operatorname{lm})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"lm")]),s("span",{class:"mclose"},")")])])]),a("] は, 光のエネルギー を示し, 眼の感度に応じて重み付けされる. 光度 [candela (cd)]は(光源から出る)立体角あたりの 光束で, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"Ω")]),s("annotation",{encoding:"application/x-tex"},"I=\\Phi / \\Omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/Ω")])])]),a(". 照度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"lux"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"l"),s("mi",{mathvariant:"normal"},"x")]),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"[\\operatorname{lux}(\\mathrm{lx})]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"lux")]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"lx")]),s("span",{class:"mclose"},")]")])])]),a(" は(面に入射する) 面積あたりの光束で, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"S")]),s("annotation",{encoding:"application/x-tex"},"E=\\Phi / S")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S")])])]),a(".")])],-1),S=s("h3",{id:"_6-10-gauss-定理",tabindex:"-1"},[a("6.10: Gauss 定理 "),s("a",{class:"header-anchor",href:"#_6-10-gauss-定理","aria-label":'Permalink to "6.10: Gauss 定理"'},"​")],-1),N=s("ol",{start:"10"},[s("li",null,[a("光束についての Gauss の定理 : 光度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"I_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" の点光源を囲 む閉曲面を通って外に出る光束は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"="),s("mn",null,"4"),s("mi",null,"π"),s("mo",null,"∑"),s("msub",null,[s("mi",null,"I"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"\\Phi=4 \\pi \\sum I_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". 光 源が 1 つで距離が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" のとき "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"E=I / r^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])],-1),q=s("h3",{id:"_6-11-実験のヒント",tabindex:"-1"},[a("6.11: 実験のヒント "),s("a",{class:"header-anchor",href:"#_6-11-実験のヒント","aria-label":'Permalink to "6.11: 実験のヒント"'},"​")],-1),E=s("ol",{start:"11"},[s("li",null,"実験のヒント:紙についた油污れが周囲の紙と同じ明 るさならば,その紙は両面から同じように照らされて いる.")],-1);function T(A,B,F,V,D,O){const l=t;return e(),m("div",null,[c,i(l,{readTime:"1",words:"428"}),h,o,g,u,d,y,x,v,w,_,b,k,f,M,z,P,L,I,S,N,q,E])}const H=n(p,[["render",T]]);export{C as __pageData,H as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as m,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 6","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/6.md","filePath":"academic/physics/ipho-formulas-jpn/6.md","lastUpdated":1699051935000}'),p={name:"academic/physics/ipho-formulas-jpn/6.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-6",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 6 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-6","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 6"'},"​")],-1),h=s("h2",{id:"_6-幾何光学-測光",tabindex:"-1"},[a("6: 幾何光学,測光 "),s("a",{class:"header-anchor",href:"#_6-幾何光学-測光","aria-label":'Permalink to "6: 幾何光学,測光"'},"​")],-1),o=s("h3",{id:"_6-1-fermat-原理",tabindex:"-1"},[a("6.1: Fermat 原理 "),s("a",{class:"header-anchor",href:"#_6-1-fermat-原理","aria-label":'Permalink to "6.1: Fermat 原理"'},"​")],-1),g=s("ol",null,[s("li",null,[a("Fermat の原理 : 点 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"A")]),s("annotation",{encoding:"application/x-tex"},"A")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"A")])])]),a(" から "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" への波の経路は波の移動 時間が最も短いもの.")])],-1),u=s("h3",{id:"_6-2-snell-法則",tabindex:"-1"},[a("6.2: Snell 法則 "),s("a",{class:"header-anchor",href:"#_6-2-snell-法則","aria-label":'Permalink to "6.2: Snell 法則"'},"​")],-1),d=s("ol",{start:"2"},[s("li",null,"Snell の法則 :")],-1),y=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"α"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("msub",null,[s("mi",null,"α"),s("mn",null,"2")]),s("mo",null,"="),s("msub",null,[s("mi",null,"n"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"n"),s("mn",null,"1")]),s("mo",null,"="),s("msub",null,[s("mi",null,"v"),s("mn",null,"1")]),s("mi",{mathvariant:"normal"},"/"),s("msub",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\sin \\alpha_1 / \\sin \\alpha_2=n_2 / n_1=v_1 / v_2 . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0037em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},".")])])])])],-1),x=s("h3",{id:"_6-3-屈折率",tabindex:"-1"},[a("6.3: 屈折率 "),s("a",{class:"header-anchor",href:"#_6-3-屈折率","aria-label":'Permalink to "6.3: 屈折率"'},"​")],-1),v=s("ol",{start:"3"},[s("li",null,[a("屈折率が連続的に変化するならば,媒質を屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n")])])]),a(" で一定のいくつかの仮想的な層に分けて Snell の 法則を適用する. 光線は屈折率一定の層に沿って進む こともでき,もし全反射の条件をわずかに満たせば, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"n"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",null,"="),s("mi",null,"n"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("mspace",{width:"1em"}),s("mo",{stretchy:"false"},"("),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"n^{\\prime}=n / r \\quad(r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"1em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" は曲率半径 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},")")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mclose"},")")])])])])],-1),w=s("h3",{id:"_6-4-屈折率な座標",tabindex:"-1"},[a("6.4: 屈折率な座標 "),s("a",{class:"header-anchor",href:"#_6-4-屈折率な座標","aria-label":'Permalink to "6.4: 屈折率な座標"'},"​")],-1),_=s("ol",{start:"4"},[s("li",null,[a("屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"z")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{z}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathrm"},"z")])])]),a(" 座標にのみ依存するならば, 光子の運動量 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"p"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"p"),s("mi",null,"y")])]),s("annotation",{encoding:"application/x-tex"},"p_x, p_y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7167em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(" とエネルギーは保存される:")])],-1),b=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"k"),s("mi",null,"x")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"k"),s("mi",null,"y")]),s("mo",null,"="),s("mtext",null," const., "),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"bold-italic"},"k"),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"n"),s("mo",null,"="),s("mtext",null," const. ")]),s("annotation",{encoding:"application/x-tex"},"k_x, k_y=\\text { const., }|\\boldsymbol{k}| / n=\\text { const. } ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.9805em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"x")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0315em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"y")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const., ")]),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.01852em"}},"k")])]),s("span",{class:"mord"},"∣/"),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6151em"}}),s("span",{class:"mord text"},[s("span",{class:"mord"}," const. ")])])])])])],-1),k=s("h3",{id:"_6-5-薄いレンズの式",tabindex:"-1"},[a("6.5:薄いレンズの式 "),s("a",{class:"header-anchor",href:"#_6-5-薄いレンズの式","aria-label":'Permalink to "6.5:薄いレンズの式"'},"​")],-1),f=s("ol",{start:"6"},[s("li",null,"薄いレンズの式(符号に注意する):")],-1),M=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"a"),s("mo",null,"+"),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"b"),s("mo",null,"="),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"f"),s("mo",null,"≡"),s("mi",null,"D")]),s("annotation",{encoding:"application/x-tex"},"1 / a+1 / b=1 / f \\equiv D ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal"},"b"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≡"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"D")])])])])],-1),z=s("h3",{id:"_6-6-newton-の式",tabindex:"-1"},[a("6.6: Newton の式 "),s("a",{class:"header-anchor",href:"#_6-6-newton-の式","aria-label":'Permalink to "6.6: Newton の式"'},"​")],-1),P=s("ol",{start:"6"},[s("li",null,[a("Newton の式 : 物体側焦点から物体までの距離を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")])]),s("annotation",{encoding:"application/x-tex"},"x_1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(", 像側焦点から像までの距離を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"x_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" とすると, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"="),s("msup",null,[s("mi",null,"f"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"x_1 x_2=f^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])],-1),L=r("",5),I=s("ol",{start:"9"},[s("li",null,[a("光束 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ")]),s("annotation",{encoding:"application/x-tex"},"\\Phi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ")])])]),a(" [単位: lumen "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"lm"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(\\operatorname{lm})")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"lm")]),s("span",{class:"mclose"},")")])])]),a("] は, 光のエネルギー を示し, 眼の感度に応じて重み付けされる. 光度 [candela (cd)]は(光源から出る)立体角あたりの 光束で, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",{mathvariant:"normal"},"Ω")]),s("annotation",{encoding:"application/x-tex"},"I=\\Phi / \\Omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/Ω")])])]),a(". 照度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"["),s("mi",{mathvariant:"normal"},"lux"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mrow",null,[s("mi",{mathvariant:"normal"},"l"),s("mi",{mathvariant:"normal"},"x")]),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"]")]),s("annotation",{encoding:"application/x-tex"},"[\\operatorname{lux}(\\mathrm{lx})]")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"["),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"lux")]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"lx")]),s("span",{class:"mclose"},")]")])])]),a(" は(面に入射する) 面積あたりの光束で, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"S")]),s("annotation",{encoding:"application/x-tex"},"E=\\Phi / S")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S")])])]),a(".")])],-1),S=s("h3",{id:"_6-10-gauss-定理",tabindex:"-1"},[a("6.10: Gauss 定理 "),s("a",{class:"header-anchor",href:"#_6-10-gauss-定理","aria-label":'Permalink to "6.10: Gauss 定理"'},"​")],-1),N=s("ol",{start:"10"},[s("li",null,[a("光束についての Gauss の定理 : 光度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"I"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"I_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" の点光源を囲 む閉曲面を通って外に出る光束は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"="),s("mn",null,"4"),s("mi",null,"π"),s("mo",null,"∑"),s("msub",null,[s("mi",null,"I"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"},"\\Phi=4 \\pi \\sum I_i")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(". 光 源が 1 つで距離が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" のとき "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"E=I / r^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])])])],-1),q=s("h3",{id:"_6-11-実験のヒント",tabindex:"-1"},[a("6.11: 実験のヒント "),s("a",{class:"header-anchor",href:"#_6-11-実験のヒント","aria-label":'Permalink to "6.11: 実験のヒント"'},"​")],-1),E=s("ol",{start:"11"},[s("li",null,"実験のヒント:紙についた油污れが周囲の紙と同じ明 るさならば,その紙は両面から同じように照らされて いる.")],-1);function T(A,B,F,V,D,O){const l=t;return e(),m("div",null,[c,i(l,{readTime:"1",words:"428"}),h,o,g,u,d,y,x,v,w,_,b,k,f,M,z,P,L,I,S,N,q,E])}const H=n(p,[["render",T]]);export{C as __pageData,H as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_7.md.353d535e.js b/assets/academic_physics_ipho-formulas-jpn_7.md.b0bd68dd.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_7.md.353d535e.js rename to assets/academic_physics_ipho-formulas-jpn_7.md.b0bd68dd.js index b0aaca7c..2fceb79b 100644 --- a/assets/academic_physics_ipho-formulas-jpn_7.md.353d535e.js +++ b/assets/academic_physics_ipho-formulas-jpn_7.md.b0bd68dd.js @@ -1,4 +1,4 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,C as i,o as p,c as r,H as l,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const ss=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 7","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/7.md","filePath":"academic/physics/ipho-formulas-jpn/7.md","lastUpdated":1695377563000}'),h={name:"academic/physics/ipho-formulas-jpn/7.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-7",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 7 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-7","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 7"'},"​")],-1),g=c('

    7: 波動光学

    7.1: Huygens の原理に基づいた回折

    1. Huygens の原理に基づいた回折 : 障害物が波面を切断 すると波面は小さな断片に分割され,それが仮想的な 点波源となり,観測点での波の振幅はこれらの波源か らの寄与の重ね合わせとなる.

    7.2: 二重スリット

    ',4),u=s("ol",{start:"2"},[s("li",null,[a("二重スリット(幅は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d"),s("mo",null,"≪"),s("mi",null,"a"),s("mo",{separator:"true"},","),s("mi",null,"λ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"d \\ll a, \\lambda)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7335em","vertical-align":"-0.0391em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")")])])]),a(" による干渉:強 め合う角 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"φ"),s("mi",null,"max"),s("mo",null,"⁡")]),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",null,"∈"),s("mi",{mathvariant:"double-struck"},"Z"),s("mi",{mathvariant:"normal"},"."),s("mi",null,"I"),s("mo",null,"∝")]),s("annotation",{encoding:"application/x-tex"},"\\varphi_{\\max }=\\arcsin (n \\lambda / d), n \\in \\mathbb{Z} . I \\propto")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mop mtight"},[s("span",{class:"mtight"},"m"),s("span",{class:"mtight"},"a"),s("span",{class:"mtight"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"nλ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord mathbb"},"Z"),s("span",{class:"mord"},"."),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"k"),s("mfrac",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("mo",{stretchy:"false"},"("),s("mi",null,"k"),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"π"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"λ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\cos ^2\\left(k \\frac{a}{2} \\sin \\varphi\\right),(k=2 \\pi / \\lambda)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"cos"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"a")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")")])])])])],-1),d=s("h3",{id:"_7-3-単スリット-弱め合う角",tabindex:"-1"},[a("7.3: 単スリット-弱め合う角 "),s("a",{class:"header-anchor",href:"#_7-3-単スリット-弱め合う角","aria-label":'Permalink to "7.3: 単スリット-弱め合う角"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("単スリット:弱め合う角: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"φ"),s("mtext",null,"min ")]),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",null,"∈")]),s("annotation",{encoding:"application/x-tex"},"\\varphi_{\\text {min }}=\\arcsin (n \\lambda / d), n \\in")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3175em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"min ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"nλ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∈")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"double-struck"},"Z"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",{mathvariant:"normal"},"≠"),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\mathbb{Z}, n \\neq 0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathbb"},"Z"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mrel"},[s("span",{class:"mord vbox"},[s("span",{class:"thinbox"},[s("span",{class:"rlap"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"inner"},[s("span",{class:"mord"},[s("span",{class:"mrel"},"")])]),s("span",{class:"fix"})])])])]),s("span",{class:"mrel"},"=")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 中央の強め合う部分は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n"),s("mo",null,"="),s("mo",null,"±"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"n=\\pm 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"±"),s("span",{class:"mord"},"1")])])]),a(" の間である ことに注意せよ. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"∝"),s("msup",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"k"),s("mfrac",null,[s("mi",null,"d"),s("mn",null,"2")]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ")]),s("annotation",{encoding:"application/x-tex"},"I \\propto \\sin ^2\\left(k \\frac{d}{2} \\sin \\varphi\\right) / \\sin \\varphi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2301em","vertical-align":"-0.35em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"sin"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8719em"}},[s("span",{style:{top:"-3.1208em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"d")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])])])])],-1),x=s("h3",{id:"_7-4-回折格子",tabindex:"-1"},[a("7.4: 回折格子 "),s("a",{class:"header-anchor",href:"#_7-4-回折格子","aria-label":'Permalink to "7.4: 回折格子"'},"​")],-1),v=s("ol",{start:"4"},[s("li",null,[a("回折格子:主な強め合う角はポイント 2 と同じで, 主 な強め合う角の幅は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" を回折格子の正味の長さとすれ ばポイント 3 と同じ. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n")])])]),a(" 番目の明線のスペクトルの分 解能は,溝の総数を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"N")]),s("annotation",{encoding:"application/x-tex"},"N")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"N")])])]),a(" 本として "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mi",null,"n"),s("mi",null,"N")]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\lambda}{\\Delta \\lambda}=n N")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"N")])])]),a(".")])],-1),w=s("h3",{id:"_7-5-分光器の分解能",tabindex:"-1"},[a("7.5: 分光器の分解能 "),s("a",{class:"header-anchor",href:"#_7-5-分光器の分解能","aria-label":'Permalink to "7.5: 分光器の分解能"'},"​")],-1),b=s("ol",{start:"5"},[s("li",null,[a("分光器の分解能 : 最短の光線と最長の光線の光学距離 の差を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"L")]),s("annotation",{encoding:"application/x-tex"},"L")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"L")])])]),a(" として, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mfrac",null,[s("mi",null,"L"),s("mi",null,"λ")])]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\lambda}{\\Delta \\lambda}=\\frac{L}{\\lambda}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2173em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(".")])],-1),k=s("h3",{id:"_7-6-プリズムの分解能",tabindex:"-1"},[a("7.6: プリズムの分解能 "),s("a",{class:"header-anchor",href:"#_7-6-プリズムの分解能","aria-label":'Permalink to "7.6: プリズムの分解能"'},"​")],-1),_=s("ol",{start:"7"},[s("li",null,[a("プリズムの分解能 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mi",null,"a"),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"n")]),s("mrow",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"λ")])])]),s("annotation",{encoding:"application/x-tex"},": \\frac{\\lambda}{\\Delta \\lambda}=a \\frac{\\mathrm{d} n}{\\mathrm{~d} \\lambda}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mspace nobreak mtight"},[s("span",{class:"mtight"}," ")]),s("span",{class:"mord mathrm mtight"},"d")]),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"d"),s("span",{class:"mord mathnormal mtight"},"n")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),f=s("h3",{id:"_7-7-角度距離",tabindex:"-1"},[a("7.7: 角度距離 "),s("a",{class:"header-anchor",href:"#_7-7-角度距離","aria-label":'Permalink to "7.7: 角度距離"'},"​")],-1),z=s("ol",{start:"7"},[s("li",null,[a("理想的な望遠鏡 (レンズ) で 2 点を解像するときの角度距離 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"φ"),s("mo",null,"≈"),s("mn",null,"1.22"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"\\varphi \\approx 1.22 \\lambda / d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6776em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.22"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d")])])]),a(". この角度では, 一方の点の中 心が他方の点の最初の回折最小值に当たる.")])],-1),M=s("h3",{id:"_7-8-bragg-の法則",tabindex:"-1"},[a("7.8: Bragg の法則 "),s("a",{class:"header-anchor",href:"#_7-8-bragg-の法則","aria-label":'Permalink to "7.8: Bragg の法則"'},"​")],-1),L=s("ol",{start:"8"},[s("li",null,[a("Bragg の法則:間隔が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" の平行な結晶面の組は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"d"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"θ"),s("mo",null,"="),s("mi",null,"n"),s("mi",null,"λ")]),s("annotation",{encoding:"application/x-tex"},"2 d \\sin \\theta=n \\lambda")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"nλ")])])]),a(" ならば "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"X")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"X")])])]),a(" 線を反射する. ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"θ")]),s("annotation",{encoding:"application/x-tex"},"\\theta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ")])])]),a(" は結 晶面と X 線がなす角 (かすめ角).")])],-1),P=s("h3",{id:"_7-9-高密度電体媒質反射",tabindex:"-1"},[a("7.9: 高密度電体媒質反射 "),s("a",{class:"header-anchor",href:"#_7-9-高密度電体媒質反射","aria-label":'Permalink to "7.9: 高密度電体媒質反射"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("光学的に高密度な誘電体媒質による反射 : 位相が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),a(" ず れる. 半透明の薄膜では "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"→")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"←")]),s("mo",null,"="),s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\rightarrow}+\\phi_{\\leftarrow}=\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"→")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"←")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),a(". ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"→")])]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\rightarrow}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"→")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"←")])]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\leftarrow}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"←")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は反射波と透過波の位相差(矢印は入射方向を 示す)")])],-1),B=s("h3",{id:"_7-10-fabry-perot-干渉計",tabindex:"-1"},[a("7.10: Fabry-Pérot 干渉計 "),s("a",{class:"header-anchor",href:"#_7-10-fabry-perot-干渉計","aria-label":'Permalink to "7.10: Fabry-Pérot 干渉計"'},"​")],-1),N=s("ol",{start:"10"},[s("li",null,[a("Fabry-Pérot 干渉計 : 高い反射率 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"r"),s("mo",null,"≪"),s("mn",null,"1"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"r(1-r \\ll 1)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")")])])]),a(" を持 つ 2 枚の平行な半透明の鏡. 分解能は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"ν"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"ν")])]),s("mo",null,"≈"),s("mfrac",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"a")]),s("mrow",null,[s("mi",null,"λ"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"r"),s("mo",{stretchy:"false"},")")])])]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\nu}{\\Delta \\nu} \\approx \\frac{2 a}{\\lambda(1-r)}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.06366em"}},"ν")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.06366em"}},"ν")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.3651em","vertical-align":"-0.52em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ"),s("span",{class:"mopen mtight"},"("),s("span",{class:"mord mtight"},"1"),s("span",{class:"mbin mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mclose mtight"},")")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight"},"a")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.52em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 5 つの平面波 (干渉計の前で左右に進む波, 内部を左右 に進む波,後ろを進む波)を設定して境界条件を課す ことで,透過スペクトルを求められる.")])],-1),q=s("h3",{id:"_7-11-コヒーレントな電磁波",tabindex:"-1"},[a("7.11: コヒーレントな電磁波 "),s("a",{class:"header-anchor",href:"#_7-11-コヒーレントな電磁波","aria-label":'Permalink to "7.11: コヒーレントな電磁波"'},"​")],-1),E=s("ol",{start:"11"},[s("li",null,[a("コヒーレントな電磁波: 電場をベクトル为で表し, ベク トル間の角度を位相差とする. 屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n"),s("mo",null,"="),s("mi",null,"n"),s("mo",{stretchy:"false"},"("),s("mi",null,"ω"),s("mo",{stretchy:"false"},")"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"n=n(\\omega)=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msqrt",null,[s("mrow",null,[s("mi",null,"ε"),s("mo",{stretchy:"false"},"("),s("mi",null,"ω"),s("mo",{stretchy:"false"},")")])])]),s("annotation",{encoding:"application/x-tex"},"\\sqrt{\\varepsilon(\\omega)}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,C as i,o as p,c as r,H as l,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const ss=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 7","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/7.md","filePath":"academic/physics/ipho-formulas-jpn/7.md","lastUpdated":1699051935000}'),h={name:"academic/physics/ipho-formulas-jpn/7.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-7",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 7 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-7","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 7"'},"​")],-1),g=c('

    7: 波動光学

    7.1: Huygens の原理に基づいた回折

    1. Huygens の原理に基づいた回折 : 障害物が波面を切断 すると波面は小さな断片に分割され,それが仮想的な 点波源となり,観測点での波の振幅はこれらの波源か らの寄与の重ね合わせとなる.

    7.2: 二重スリット

    ',4),u=s("ol",{start:"2"},[s("li",null,[a("二重スリット(幅は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d"),s("mo",null,"≪"),s("mi",null,"a"),s("mo",{separator:"true"},","),s("mi",null,"λ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"d \\ll a, \\lambda)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7335em","vertical-align":"-0.0391em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")")])])]),a(" による干渉:強 め合う角 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"φ"),s("mi",null,"max"),s("mo",null,"⁡")]),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",null,"∈"),s("mi",{mathvariant:"double-struck"},"Z"),s("mi",{mathvariant:"normal"},"."),s("mi",null,"I"),s("mo",null,"∝")]),s("annotation",{encoding:"application/x-tex"},"\\varphi_{\\max }=\\arcsin (n \\lambda / d), n \\in \\mathbb{Z} . I \\propto")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mop mtight"},[s("span",{class:"mtight"},"m"),s("span",{class:"mtight"},"a"),s("span",{class:"mtight"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"nλ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord mathbb"},"Z"),s("span",{class:"mord"},"."),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"k"),s("mfrac",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("mo",{stretchy:"false"},"("),s("mi",null,"k"),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"π"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"λ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\cos ^2\\left(k \\frac{a}{2} \\sin \\varphi\\right),(k=2 \\pi / \\lambda)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"cos"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"a")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")")])])])])],-1),d=s("h3",{id:"_7-3-単スリット-弱め合う角",tabindex:"-1"},[a("7.3: 単スリット-弱め合う角 "),s("a",{class:"header-anchor",href:"#_7-3-単スリット-弱め合う角","aria-label":'Permalink to "7.3: 単スリット-弱め合う角"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("単スリット:弱め合う角: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"φ"),s("mtext",null,"min ")]),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",null,"∈")]),s("annotation",{encoding:"application/x-tex"},"\\varphi_{\\text {min }}=\\arcsin (n \\lambda / d), n \\in")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3175em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"min ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"nλ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∈")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"double-struck"},"Z"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",{mathvariant:"normal"},"≠"),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\mathbb{Z}, n \\neq 0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathbb"},"Z"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mrel"},[s("span",{class:"mord vbox"},[s("span",{class:"thinbox"},[s("span",{class:"rlap"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"inner"},[s("span",{class:"mord"},[s("span",{class:"mrel"},"")])]),s("span",{class:"fix"})])])])]),s("span",{class:"mrel"},"=")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 中央の強め合う部分は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n"),s("mo",null,"="),s("mo",null,"±"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"n=\\pm 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"±"),s("span",{class:"mord"},"1")])])]),a(" の間である ことに注意せよ. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"∝"),s("msup",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"k"),s("mfrac",null,[s("mi",null,"d"),s("mn",null,"2")]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ")]),s("annotation",{encoding:"application/x-tex"},"I \\propto \\sin ^2\\left(k \\frac{d}{2} \\sin \\varphi\\right) / \\sin \\varphi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2301em","vertical-align":"-0.35em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"sin"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8719em"}},[s("span",{style:{top:"-3.1208em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"d")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])])])])],-1),x=s("h3",{id:"_7-4-回折格子",tabindex:"-1"},[a("7.4: 回折格子 "),s("a",{class:"header-anchor",href:"#_7-4-回折格子","aria-label":'Permalink to "7.4: 回折格子"'},"​")],-1),v=s("ol",{start:"4"},[s("li",null,[a("回折格子:主な強め合う角はポイント 2 と同じで, 主 な強め合う角の幅は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" を回折格子の正味の長さとすれ ばポイント 3 と同じ. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n")])])]),a(" 番目の明線のスペクトルの分 解能は,溝の総数を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"N")]),s("annotation",{encoding:"application/x-tex"},"N")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"N")])])]),a(" 本として "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mi",null,"n"),s("mi",null,"N")]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\lambda}{\\Delta \\lambda}=n N")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"N")])])]),a(".")])],-1),w=s("h3",{id:"_7-5-分光器の分解能",tabindex:"-1"},[a("7.5: 分光器の分解能 "),s("a",{class:"header-anchor",href:"#_7-5-分光器の分解能","aria-label":'Permalink to "7.5: 分光器の分解能"'},"​")],-1),b=s("ol",{start:"5"},[s("li",null,[a("分光器の分解能 : 最短の光線と最長の光線の光学距離 の差を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"L")]),s("annotation",{encoding:"application/x-tex"},"L")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"L")])])]),a(" として, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mfrac",null,[s("mi",null,"L"),s("mi",null,"λ")])]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\lambda}{\\Delta \\lambda}=\\frac{L}{\\lambda}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2173em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(".")])],-1),k=s("h3",{id:"_7-6-プリズムの分解能",tabindex:"-1"},[a("7.6: プリズムの分解能 "),s("a",{class:"header-anchor",href:"#_7-6-プリズムの分解能","aria-label":'Permalink to "7.6: プリズムの分解能"'},"​")],-1),_=s("ol",{start:"7"},[s("li",null,[a("プリズムの分解能 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mi",null,"a"),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"n")]),s("mrow",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"λ")])])]),s("annotation",{encoding:"application/x-tex"},": \\frac{\\lambda}{\\Delta \\lambda}=a \\frac{\\mathrm{d} n}{\\mathrm{~d} \\lambda}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mspace nobreak mtight"},[s("span",{class:"mtight"}," ")]),s("span",{class:"mord mathrm mtight"},"d")]),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"d"),s("span",{class:"mord mathnormal mtight"},"n")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),f=s("h3",{id:"_7-7-角度距離",tabindex:"-1"},[a("7.7: 角度距離 "),s("a",{class:"header-anchor",href:"#_7-7-角度距離","aria-label":'Permalink to "7.7: 角度距離"'},"​")],-1),z=s("ol",{start:"7"},[s("li",null,[a("理想的な望遠鏡 (レンズ) で 2 点を解像するときの角度距離 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"φ"),s("mo",null,"≈"),s("mn",null,"1.22"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"\\varphi \\approx 1.22 \\lambda / d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6776em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.22"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d")])])]),a(". この角度では, 一方の点の中 心が他方の点の最初の回折最小值に当たる.")])],-1),M=s("h3",{id:"_7-8-bragg-の法則",tabindex:"-1"},[a("7.8: Bragg の法則 "),s("a",{class:"header-anchor",href:"#_7-8-bragg-の法則","aria-label":'Permalink to "7.8: Bragg の法則"'},"​")],-1),L=s("ol",{start:"8"},[s("li",null,[a("Bragg の法則:間隔が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" の平行な結晶面の組は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"d"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"θ"),s("mo",null,"="),s("mi",null,"n"),s("mi",null,"λ")]),s("annotation",{encoding:"application/x-tex"},"2 d \\sin \\theta=n \\lambda")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"nλ")])])]),a(" ならば "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"X")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"X")])])]),a(" 線を反射する. ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"θ")]),s("annotation",{encoding:"application/x-tex"},"\\theta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ")])])]),a(" は結 晶面と X 線がなす角 (かすめ角).")])],-1),P=s("h3",{id:"_7-9-高密度電体媒質反射",tabindex:"-1"},[a("7.9: 高密度電体媒質反射 "),s("a",{class:"header-anchor",href:"#_7-9-高密度電体媒質反射","aria-label":'Permalink to "7.9: 高密度電体媒質反射"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("光学的に高密度な誘電体媒質による反射 : 位相が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),a(" ず れる. 半透明の薄膜では "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"→")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"←")]),s("mo",null,"="),s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\rightarrow}+\\phi_{\\leftarrow}=\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"→")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"←")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),a(". ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"→")])]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\rightarrow}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"→")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"←")])]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\leftarrow}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"←")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は反射波と透過波の位相差(矢印は入射方向を 示す)")])],-1),B=s("h3",{id:"_7-10-fabry-perot-干渉計",tabindex:"-1"},[a("7.10: Fabry-Pérot 干渉計 "),s("a",{class:"header-anchor",href:"#_7-10-fabry-perot-干渉計","aria-label":'Permalink to "7.10: Fabry-Pérot 干渉計"'},"​")],-1),N=s("ol",{start:"10"},[s("li",null,[a("Fabry-Pérot 干渉計 : 高い反射率 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"r"),s("mo",null,"≪"),s("mn",null,"1"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"r(1-r \\ll 1)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")")])])]),a(" を持 つ 2 枚の平行な半透明の鏡. 分解能は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"ν"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"ν")])]),s("mo",null,"≈"),s("mfrac",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"a")]),s("mrow",null,[s("mi",null,"λ"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"r"),s("mo",{stretchy:"false"},")")])])]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\nu}{\\Delta \\nu} \\approx \\frac{2 a}{\\lambda(1-r)}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.06366em"}},"ν")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.06366em"}},"ν")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.3651em","vertical-align":"-0.52em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ"),s("span",{class:"mopen mtight"},"("),s("span",{class:"mord mtight"},"1"),s("span",{class:"mbin mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mclose mtight"},")")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight"},"a")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.52em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 5 つの平面波 (干渉計の前で左右に進む波, 内部を左右 に進む波,後ろを進む波)を設定して境界条件を課す ことで,透過スペクトルを求められる.")])],-1),q=s("h3",{id:"_7-11-コヒーレントな電磁波",tabindex:"-1"},[a("7.11: コヒーレントな電磁波 "),s("a",{class:"header-anchor",href:"#_7-11-コヒーレントな電磁波","aria-label":'Permalink to "7.11: コヒーレントな電磁波"'},"​")],-1),E=s("ol",{start:"11"},[s("li",null,[a("コヒーレントな電磁波: 電場をベクトル为で表し, ベク トル間の角度を位相差とする. 屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n"),s("mo",null,"="),s("mi",null,"n"),s("mo",{stretchy:"false"},"("),s("mi",null,"ω"),s("mo",{stretchy:"false"},")"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"n=n(\\omega)=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msqrt",null,[s("mrow",null,[s("mi",null,"ε"),s("mo",{stretchy:"false"},"("),s("mi",null,"ω"),s("mo",{stretchy:"false"},")")])])]),s("annotation",{encoding:"application/x-tex"},"\\sqrt{\\varepsilon(\\omega)}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 c340,-704.7,510.7,-1060.3,512,-1067 l0 -0 diff --git a/assets/academic_physics_ipho-formulas-jpn_7.md.353d535e.lean.js b/assets/academic_physics_ipho-formulas-jpn_7.md.b0bd68dd.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_7.md.353d535e.lean.js rename to assets/academic_physics_ipho-formulas-jpn_7.md.b0bd68dd.lean.js index ac7e36b8..3b19d9f7 100644 --- a/assets/academic_physics_ipho-formulas-jpn_7.md.353d535e.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_7.md.b0bd68dd.lean.js @@ -1,4 +1,4 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,C as i,o as p,c as r,H as l,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const ss=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 7","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/7.md","filePath":"academic/physics/ipho-formulas-jpn/7.md","lastUpdated":1695377563000}'),h={name:"academic/physics/ipho-formulas-jpn/7.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-7",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 7 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-7","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 7"'},"​")],-1),g=c("",4),u=s("ol",{start:"2"},[s("li",null,[a("二重スリット(幅は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d"),s("mo",null,"≪"),s("mi",null,"a"),s("mo",{separator:"true"},","),s("mi",null,"λ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"d \\ll a, \\lambda)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7335em","vertical-align":"-0.0391em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")")])])]),a(" による干渉:強 め合う角 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"φ"),s("mi",null,"max"),s("mo",null,"⁡")]),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",null,"∈"),s("mi",{mathvariant:"double-struck"},"Z"),s("mi",{mathvariant:"normal"},"."),s("mi",null,"I"),s("mo",null,"∝")]),s("annotation",{encoding:"application/x-tex"},"\\varphi_{\\max }=\\arcsin (n \\lambda / d), n \\in \\mathbb{Z} . I \\propto")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mop mtight"},[s("span",{class:"mtight"},"m"),s("span",{class:"mtight"},"a"),s("span",{class:"mtight"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"nλ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord mathbb"},"Z"),s("span",{class:"mord"},"."),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"k"),s("mfrac",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("mo",{stretchy:"false"},"("),s("mi",null,"k"),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"π"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"λ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\cos ^2\\left(k \\frac{a}{2} \\sin \\varphi\\right),(k=2 \\pi / \\lambda)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"cos"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"a")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")")])])])])],-1),d=s("h3",{id:"_7-3-単スリット-弱め合う角",tabindex:"-1"},[a("7.3: 単スリット-弱め合う角 "),s("a",{class:"header-anchor",href:"#_7-3-単スリット-弱め合う角","aria-label":'Permalink to "7.3: 単スリット-弱め合う角"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("単スリット:弱め合う角: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"φ"),s("mtext",null,"min ")]),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",null,"∈")]),s("annotation",{encoding:"application/x-tex"},"\\varphi_{\\text {min }}=\\arcsin (n \\lambda / d), n \\in")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3175em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"min ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"nλ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∈")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"double-struck"},"Z"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",{mathvariant:"normal"},"≠"),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\mathbb{Z}, n \\neq 0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathbb"},"Z"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mrel"},[s("span",{class:"mord vbox"},[s("span",{class:"thinbox"},[s("span",{class:"rlap"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"inner"},[s("span",{class:"mord"},[s("span",{class:"mrel"},"")])]),s("span",{class:"fix"})])])])]),s("span",{class:"mrel"},"=")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 中央の強め合う部分は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n"),s("mo",null,"="),s("mo",null,"±"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"n=\\pm 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"±"),s("span",{class:"mord"},"1")])])]),a(" の間である ことに注意せよ. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"∝"),s("msup",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"k"),s("mfrac",null,[s("mi",null,"d"),s("mn",null,"2")]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ")]),s("annotation",{encoding:"application/x-tex"},"I \\propto \\sin ^2\\left(k \\frac{d}{2} \\sin \\varphi\\right) / \\sin \\varphi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2301em","vertical-align":"-0.35em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"sin"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8719em"}},[s("span",{style:{top:"-3.1208em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"d")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])])])])],-1),x=s("h3",{id:"_7-4-回折格子",tabindex:"-1"},[a("7.4: 回折格子 "),s("a",{class:"header-anchor",href:"#_7-4-回折格子","aria-label":'Permalink to "7.4: 回折格子"'},"​")],-1),v=s("ol",{start:"4"},[s("li",null,[a("回折格子:主な強め合う角はポイント 2 と同じで, 主 な強め合う角の幅は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" を回折格子の正味の長さとすれ ばポイント 3 と同じ. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n")])])]),a(" 番目の明線のスペクトルの分 解能は,溝の総数を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"N")]),s("annotation",{encoding:"application/x-tex"},"N")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"N")])])]),a(" 本として "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mi",null,"n"),s("mi",null,"N")]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\lambda}{\\Delta \\lambda}=n N")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"N")])])]),a(".")])],-1),w=s("h3",{id:"_7-5-分光器の分解能",tabindex:"-1"},[a("7.5: 分光器の分解能 "),s("a",{class:"header-anchor",href:"#_7-5-分光器の分解能","aria-label":'Permalink to "7.5: 分光器の分解能"'},"​")],-1),b=s("ol",{start:"5"},[s("li",null,[a("分光器の分解能 : 最短の光線と最長の光線の光学距離 の差を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"L")]),s("annotation",{encoding:"application/x-tex"},"L")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"L")])])]),a(" として, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mfrac",null,[s("mi",null,"L"),s("mi",null,"λ")])]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\lambda}{\\Delta \\lambda}=\\frac{L}{\\lambda}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2173em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(".")])],-1),k=s("h3",{id:"_7-6-プリズムの分解能",tabindex:"-1"},[a("7.6: プリズムの分解能 "),s("a",{class:"header-anchor",href:"#_7-6-プリズムの分解能","aria-label":'Permalink to "7.6: プリズムの分解能"'},"​")],-1),_=s("ol",{start:"7"},[s("li",null,[a("プリズムの分解能 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mi",null,"a"),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"n")]),s("mrow",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"λ")])])]),s("annotation",{encoding:"application/x-tex"},": \\frac{\\lambda}{\\Delta \\lambda}=a \\frac{\\mathrm{d} n}{\\mathrm{~d} \\lambda}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mspace nobreak mtight"},[s("span",{class:"mtight"}," ")]),s("span",{class:"mord mathrm mtight"},"d")]),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"d"),s("span",{class:"mord mathnormal mtight"},"n")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),f=s("h3",{id:"_7-7-角度距離",tabindex:"-1"},[a("7.7: 角度距離 "),s("a",{class:"header-anchor",href:"#_7-7-角度距離","aria-label":'Permalink to "7.7: 角度距離"'},"​")],-1),z=s("ol",{start:"7"},[s("li",null,[a("理想的な望遠鏡 (レンズ) で 2 点を解像するときの角度距離 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"φ"),s("mo",null,"≈"),s("mn",null,"1.22"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"\\varphi \\approx 1.22 \\lambda / d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6776em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.22"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d")])])]),a(". この角度では, 一方の点の中 心が他方の点の最初の回折最小值に当たる.")])],-1),M=s("h3",{id:"_7-8-bragg-の法則",tabindex:"-1"},[a("7.8: Bragg の法則 "),s("a",{class:"header-anchor",href:"#_7-8-bragg-の法則","aria-label":'Permalink to "7.8: Bragg の法則"'},"​")],-1),L=s("ol",{start:"8"},[s("li",null,[a("Bragg の法則:間隔が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" の平行な結晶面の組は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"d"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"θ"),s("mo",null,"="),s("mi",null,"n"),s("mi",null,"λ")]),s("annotation",{encoding:"application/x-tex"},"2 d \\sin \\theta=n \\lambda")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"nλ")])])]),a(" ならば "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"X")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"X")])])]),a(" 線を反射する. ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"θ")]),s("annotation",{encoding:"application/x-tex"},"\\theta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ")])])]),a(" は結 晶面と X 線がなす角 (かすめ角).")])],-1),P=s("h3",{id:"_7-9-高密度電体媒質反射",tabindex:"-1"},[a("7.9: 高密度電体媒質反射 "),s("a",{class:"header-anchor",href:"#_7-9-高密度電体媒質反射","aria-label":'Permalink to "7.9: 高密度電体媒質反射"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("光学的に高密度な誘電体媒質による反射 : 位相が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),a(" ず れる. 半透明の薄膜では "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"→")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"←")]),s("mo",null,"="),s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\rightarrow}+\\phi_{\\leftarrow}=\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"→")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"←")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),a(". ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"→")])]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\rightarrow}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"→")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"←")])]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\leftarrow}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"←")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は反射波と透過波の位相差(矢印は入射方向を 示す)")])],-1),B=s("h3",{id:"_7-10-fabry-perot-干渉計",tabindex:"-1"},[a("7.10: Fabry-Pérot 干渉計 "),s("a",{class:"header-anchor",href:"#_7-10-fabry-perot-干渉計","aria-label":'Permalink to "7.10: Fabry-Pérot 干渉計"'},"​")],-1),N=s("ol",{start:"10"},[s("li",null,[a("Fabry-Pérot 干渉計 : 高い反射率 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"r"),s("mo",null,"≪"),s("mn",null,"1"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"r(1-r \\ll 1)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")")])])]),a(" を持 つ 2 枚の平行な半透明の鏡. 分解能は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"ν"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"ν")])]),s("mo",null,"≈"),s("mfrac",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"a")]),s("mrow",null,[s("mi",null,"λ"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"r"),s("mo",{stretchy:"false"},")")])])]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\nu}{\\Delta \\nu} \\approx \\frac{2 a}{\\lambda(1-r)}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.06366em"}},"ν")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.06366em"}},"ν")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.3651em","vertical-align":"-0.52em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ"),s("span",{class:"mopen mtight"},"("),s("span",{class:"mord mtight"},"1"),s("span",{class:"mbin mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mclose mtight"},")")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight"},"a")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.52em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 5 つの平面波 (干渉計の前で左右に進む波, 内部を左右 に進む波,後ろを進む波)を設定して境界条件を課す ことで,透過スペクトルを求められる.")])],-1),q=s("h3",{id:"_7-11-コヒーレントな電磁波",tabindex:"-1"},[a("7.11: コヒーレントな電磁波 "),s("a",{class:"header-anchor",href:"#_7-11-コヒーレントな電磁波","aria-label":'Permalink to "7.11: コヒーレントな電磁波"'},"​")],-1),E=s("ol",{start:"11"},[s("li",null,[a("コヒーレントな電磁波: 電場をベクトル为で表し, ベク トル間の角度を位相差とする. 屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n"),s("mo",null,"="),s("mi",null,"n"),s("mo",{stretchy:"false"},"("),s("mi",null,"ω"),s("mo",{stretchy:"false"},")"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"n=n(\\omega)=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msqrt",null,[s("mrow",null,[s("mi",null,"ε"),s("mo",{stretchy:"false"},"("),s("mi",null,"ω"),s("mo",{stretchy:"false"},")")])])]),s("annotation",{encoding:"application/x-tex"},"\\sqrt{\\varepsilon(\\omega)}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,C as i,o as p,c as r,H as l,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const ss=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 7","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/7.md","filePath":"academic/physics/ipho-formulas-jpn/7.md","lastUpdated":1699051935000}'),h={name:"academic/physics/ipho-formulas-jpn/7.md"},o=s("h1",{id:"formulas-for-ipho-日本語版-section-7",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 7 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-7","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 7"'},"​")],-1),g=c("",4),u=s("ol",{start:"2"},[s("li",null,[a("二重スリット(幅は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d"),s("mo",null,"≪"),s("mi",null,"a"),s("mo",{separator:"true"},","),s("mi",null,"λ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"d \\ll a, \\lambda)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7335em","vertical-align":"-0.0391em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")")])])]),a(" による干渉:強 め合う角 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"φ"),s("mi",null,"max"),s("mo",null,"⁡")]),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",null,"∈"),s("mi",{mathvariant:"double-struck"},"Z"),s("mi",{mathvariant:"normal"},"."),s("mi",null,"I"),s("mo",null,"∝")]),s("annotation",{encoding:"application/x-tex"},"\\varphi_{\\max }=\\arcsin (n \\lambda / d), n \\in \\mathbb{Z} . I \\propto")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mop mtight"},[s("span",{class:"mtight"},"m"),s("span",{class:"mtight"},"a"),s("span",{class:"mtight"},"x")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"nλ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6889em"}}),s("span",{class:"mord mathbb"},"Z"),s("span",{class:"mord"},"."),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mrow",null,[s("mi",null,"cos"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"k"),s("mfrac",null,[s("mi",null,"a"),s("mn",null,"2")]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{fence:"true"},")")]),s("mo",{separator:"true"},","),s("mo",{stretchy:"false"},"("),s("mi",null,"k"),s("mo",null,"="),s("mn",null,"2"),s("mi",null,"π"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"λ"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"\\cos ^2\\left(k \\frac{a}{2} \\sin \\varphi\\right),(k=2 \\pi / \\lambda)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"cos"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"a")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mclose"},")")])])])])],-1),d=s("h3",{id:"_7-3-単スリット-弱め合う角",tabindex:"-1"},[a("7.3: 単スリット-弱め合う角 "),s("a",{class:"header-anchor",href:"#_7-3-単スリット-弱め合う角","aria-label":'Permalink to "7.3: 単スリット-弱め合う角"'},"​")],-1),y=s("ol",{start:"3"},[s("li",null,[a("単スリット:弱め合う角: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"φ"),s("mtext",null,"min ")]),s("mo",null,"="),s("mi",null,"arcsin"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"n"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",null,"∈")]),s("annotation",{encoding:"application/x-tex"},"\\varphi_{\\text {min }}=\\arcsin (n \\lambda / d), n \\in")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3175em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"min ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mop"},"arcsin"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"nλ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∈")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"double-struck"},"Z"),s("mo",{separator:"true"},","),s("mi",null,"n"),s("mo",{mathvariant:"normal"},"≠"),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\mathbb{Z}, n \\neq 0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathbb"},"Z"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},[s("span",{class:"mrel"},[s("span",{class:"mord vbox"},[s("span",{class:"thinbox"},[s("span",{class:"rlap"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"inner"},[s("span",{class:"mord"},[s("span",{class:"mrel"},"")])]),s("span",{class:"fix"})])])])]),s("span",{class:"mrel"},"=")]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 中央の強め合う部分は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n"),s("mo",null,"="),s("mo",null,"±"),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"n=\\pm 1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"±"),s("span",{class:"mord"},"1")])])]),a(" の間である ことに注意せよ. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I"),s("mo",null,"∝"),s("msup",null,[s("mrow",null,[s("mi",null,"sin"),s("mo",null,"⁡")]),s("mn",null,"2")]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"k"),s("mfrac",null,[s("mi",null,"d"),s("mn",null,"2")]),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ"),s("mo",{fence:"true"},")")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"φ")]),s("annotation",{encoding:"application/x-tex"},"I \\propto \\sin ^2\\left(k \\frac{d}{2} \\sin \\varphi\\right) / \\sin \\varphi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2301em","vertical-align":"-0.35em"}}),s("span",{class:"mop"},[s("span",{class:"mop"},"sin"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8719em"}},[s("span",{style:{top:"-3.1208em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"d")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"/"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"φ")])])])])],-1),x=s("h3",{id:"_7-4-回折格子",tabindex:"-1"},[a("7.4: 回折格子 "),s("a",{class:"header-anchor",href:"#_7-4-回折格子","aria-label":'Permalink to "7.4: 回折格子"'},"​")],-1),v=s("ol",{start:"4"},[s("li",null,[a("回折格子:主な強め合う角はポイント 2 と同じで, 主 な強め合う角の幅は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" を回折格子の正味の長さとすれ ばポイント 3 と同じ. "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n")]),s("annotation",{encoding:"application/x-tex"},"n")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n")])])]),a(" 番目の明線のスペクトルの分 解能は,溝の総数を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"N")]),s("annotation",{encoding:"application/x-tex"},"N")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"N")])])]),a(" 本として "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mi",null,"n"),s("mi",null,"N")]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\lambda}{\\Delta \\lambda}=n N")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"N")])])]),a(".")])],-1),w=s("h3",{id:"_7-5-分光器の分解能",tabindex:"-1"},[a("7.5: 分光器の分解能 "),s("a",{class:"header-anchor",href:"#_7-5-分光器の分解能","aria-label":'Permalink to "7.5: 分光器の分解能"'},"​")],-1),b=s("ol",{start:"5"},[s("li",null,[a("分光器の分解能 : 最短の光線と最長の光線の光学距離 の差を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"L")]),s("annotation",{encoding:"application/x-tex"},"L")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"L")])])]),a(" として, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mfrac",null,[s("mi",null,"L"),s("mi",null,"λ")])]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\lambda}{\\Delta \\lambda}=\\frac{L}{\\lambda}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2173em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(".")])],-1),k=s("h3",{id:"_7-6-プリズムの分解能",tabindex:"-1"},[a("7.6: プリズムの分解能 "),s("a",{class:"header-anchor",href:"#_7-6-プリズムの分解能","aria-label":'Permalink to "7.6: プリズムの分解能"'},"​")],-1),_=s("ol",{start:"7"},[s("li",null,[a("プリズムの分解能 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("mfrac",null,[s("mi",null,"λ"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"λ")])]),s("mo",null,"="),s("mi",null,"a"),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",null,"n")]),s("mrow",null,[s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"λ")])])]),s("annotation",{encoding:"application/x-tex"},": \\frac{\\lambda}{\\Delta \\lambda}=a \\frac{\\mathrm{d} n}{\\mathrm{~d} \\lambda}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2251em","vertical-align":"-0.345em"}}),s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8801em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mspace nobreak mtight"},[s("span",{class:"mtight"}," ")]),s("span",{class:"mord mathrm mtight"},"d")]),s("span",{class:"mord mathnormal mtight"},"λ")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathrm mtight"},"d"),s("span",{class:"mord mathnormal mtight"},"n")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),f=s("h3",{id:"_7-7-角度距離",tabindex:"-1"},[a("7.7: 角度距離 "),s("a",{class:"header-anchor",href:"#_7-7-角度距離","aria-label":'Permalink to "7.7: 角度距離"'},"​")],-1),z=s("ol",{start:"7"},[s("li",null,[a("理想的な望遠鏡 (レンズ) で 2 点を解像するときの角度距離 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"φ"),s("mo",null,"≈"),s("mn",null,"1.22"),s("mi",null,"λ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"\\varphi \\approx 1.22 \\lambda / d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6776em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1.22"),s("span",{class:"mord mathnormal"},"λ"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d")])])]),a(". この角度では, 一方の点の中 心が他方の点の最初の回折最小值に当たる.")])],-1),M=s("h3",{id:"_7-8-bragg-の法則",tabindex:"-1"},[a("7.8: Bragg の法則 "),s("a",{class:"header-anchor",href:"#_7-8-bragg-の法則","aria-label":'Permalink to "7.8: Bragg の法則"'},"​")],-1),L=s("ol",{start:"8"},[s("li",null,[a("Bragg の法則:間隔が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" の平行な結晶面の組は, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"d"),s("mi",null,"sin"),s("mo",null,"⁡"),s("mi",null,"θ"),s("mo",null,"="),s("mi",null,"n"),s("mi",null,"λ")]),s("annotation",{encoding:"application/x-tex"},"2 d \\sin \\theta=n \\lambda")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"sin"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"nλ")])])]),a(" ならば "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"X")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{X}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathrm"},"X")])])]),a(" 線を反射する. ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"θ")]),s("annotation",{encoding:"application/x-tex"},"\\theta")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"θ")])])]),a(" は結 晶面と X 線がなす角 (かすめ角).")])],-1),P=s("h3",{id:"_7-9-高密度電体媒質反射",tabindex:"-1"},[a("7.9: 高密度電体媒質反射 "),s("a",{class:"header-anchor",href:"#_7-9-高密度電体媒質反射","aria-label":'Permalink to "7.9: 高密度電体媒質反射"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("光学的に高密度な誘電体媒質による反射 : 位相が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),a(" ず れる. 半透明の薄膜では "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"→")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"←")]),s("mo",null,"="),s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\rightarrow}+\\phi_{\\leftarrow}=\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"→")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"←")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),a(". ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"→")])]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\rightarrow}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"→")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"ϕ"),s("mo",{lspace:"0em",rspace:"0em"},"←")])]),s("annotation",{encoding:"application/x-tex"},"\\phi_{\\leftarrow}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1068em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"←")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" は反射波と透過波の位相差(矢印は入射方向を 示す)")])],-1),B=s("h3",{id:"_7-10-fabry-perot-干渉計",tabindex:"-1"},[a("7.10: Fabry-Pérot 干渉計 "),s("a",{class:"header-anchor",href:"#_7-10-fabry-perot-干渉計","aria-label":'Permalink to "7.10: Fabry-Pérot 干渉計"'},"​")],-1),N=s("ol",{start:"10"},[s("li",null,[a("Fabry-Pérot 干渉計 : 高い反射率 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"r"),s("mo",null,"≪"),s("mn",null,"1"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"r(1-r \\ll 1)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≪"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")")])])]),a(" を持 つ 2 枚の平行な半透明の鏡. 分解能は "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("mi",null,"ν"),s("mrow",null,[s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"ν")])]),s("mo",null,"≈"),s("mfrac",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"a")]),s("mrow",null,[s("mi",null,"λ"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"−"),s("mi",null,"r"),s("mo",{stretchy:"false"},")")])])]),s("annotation",{encoding:"application/x-tex"},"\\frac{\\nu}{\\Delta \\nu} \\approx \\frac{2 a}{\\lambda(1-r)}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"Δ"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.06366em"}},"ν")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.06366em"}},"ν")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.3651em","vertical-align":"-0.52em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8451em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"λ"),s("span",{class:"mopen mtight"},"("),s("span",{class:"mord mtight"},"1"),s("span",{class:"mbin mtight"},"−"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mclose mtight"},")")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight"},"a")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.52em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 5 つの平面波 (干渉計の前で左右に進む波, 内部を左右 に進む波,後ろを進む波)を設定して境界条件を課す ことで,透過スペクトルを求められる.")])],-1),q=s("h3",{id:"_7-11-コヒーレントな電磁波",tabindex:"-1"},[a("7.11: コヒーレントな電磁波 "),s("a",{class:"header-anchor",href:"#_7-11-コヒーレントな電磁波","aria-label":'Permalink to "7.11: コヒーレントな電磁波"'},"​")],-1),E=s("ol",{start:"11"},[s("li",null,[a("コヒーレントな電磁波: 電場をベクトル为で表し, ベク トル間の角度を位相差とする. 屈折率が "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"n"),s("mo",null,"="),s("mi",null,"n"),s("mo",{stretchy:"false"},"("),s("mi",null,"ω"),s("mo",{stretchy:"false"},")"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"n=n(\\omega)=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msqrt",null,[s("mrow",null,[s("mi",null,"ε"),s("mo",{stretchy:"false"},"("),s("mi",null,"ω"),s("mo",{stretchy:"false"},")")])])]),s("annotation",{encoding:"application/x-tex"},"\\sqrt{\\varepsilon(\\omega)}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.24em","vertical-align":"-0.305em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.935em"}},[s("span",{class:"svg-align",style:{top:"-3.2em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"mord",style:{"padding-left":"1em"}},[s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"mclose"},")")])]),s("span",{style:{top:"-2.895em"}},[s("span",{class:"pstrut",style:{height:"3.2em"}}),s("span",{class:"hide-tail",style:{"min-width":"1.02em",height:"1.28em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.28em",viewBox:"0 0 400000 1296",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M263,681c0.7,0,18,39.7,52,119 c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 c340,-704.7,510.7,-1060.3,512,-1067 l0 -0 diff --git a/assets/academic_physics_ipho-formulas-jpn_8.md.f1df91b7.js b/assets/academic_physics_ipho-formulas-jpn_8.md.f05c02fb.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_8.md.f1df91b7.js rename to assets/academic_physics_ipho-formulas-jpn_8.md.f05c02fb.js index 79f102a0..8dee8017 100644 --- a/assets/academic_physics_ipho-formulas-jpn_8.md.f1df91b7.js +++ b/assets/academic_physics_ipho-formulas-jpn_8.md.f05c02fb.js @@ -1,4 +1,4 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const F=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 8","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/8.md","filePath":"academic/physics/ipho-formulas-jpn/8.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/8.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-8",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 8 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-8","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 8"'},"​")],-1),h=s("h2",{id:"_8-電気回路",tabindex:"-1"},[a("8: 電気回路 "),s("a",{class:"header-anchor",href:"#_8-電気回路","aria-label":'Permalink to "8: 電気回路"'},"​")],-1),o=s("h3",{id:"_8-1-v-i-r-p-v-i",tabindex:"-1"},[a("8.1: V=I R, P=V I "),s("a",{class:"header-anchor",href:"#_8-1-v-i-r-p-v-i","aria-label":'Permalink to "8.1: V=I R, P=V I"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"V"),s("mo",null,"="),s("mi",null,"I"),s("mi",null,"R"),s("mo",{separator:"true"},","),s("mi",null,"P"),s("mo",null,"="),s("mi",null,"V"),s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"V=I R, P=V I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"R"),s("mtext",null,"直列 ")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"R"),s("mi",null,"i")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"R"),s("mtext",null,"並列 "),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"="),s("mo",null,"∑"),s("msubsup",null,[s("mi",null,"R"),s("mi",null,"i"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])]),s("annotation",{encoding:"application/x-tex"},"R_{\\text {直列 }}=\\sum R_i, R_{\\text {並列 }}^{-1}=\\sum R_i^{-1} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"直列"),s("span",{class:"mord mtight"}," ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.4163em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"並列"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2837em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.433em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.267em"}},[s("span")])])])])])])])])])])])],-1),u=s("h3",{id:"_8-2-kirchhoff-の法則",tabindex:"-1"},[a("8.2: Kirchhoff の法則 "),s("a",{class:"header-anchor",href:"#_8-2-kirchhoff-の法則","aria-label":'Permalink to "8.2: Kirchhoff の法則"'},"​")],-1),d=s("ol",{start:"2"},[s("li",null,[a("Kirchhoff の法則 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("munder",null,[s("mo",null,"∑"),s("mstyle",{scriptlevel:"1"},[s("mtable",{rowspacing:"0.1em",columnalign:"center",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"1",displaystyle:"false"},[s("mtext",null," 節点 ")])])])])])]),s("mi",null,"I"),s("mo",null,"="),s("mn",null,"0"),s("mo",{separator:"true"},","),s("munder",null,[s("mo",null,"∑"),s("mtext",null,"閉路 ")]),s("mi",null,"V"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\sum_{\\substack{\\text { 節点 }}} I=0, \\sum_{\\text {閉路 }} V=0 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4703em","vertical-align":"-1.4203em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.05em"}},[s("span",{style:{top:"-1.8568em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6817em"}},[s("span",{style:{top:"-2.6983em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"}," "),s("span",{class:"mord cjk_fallback mtight"},"節点"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1817em"}},[s("span")])])])])])])])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.4203em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.3443em","vertical-align":"-1.2943em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.05em"}},[s("span",{style:{top:"-1.8557em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"閉路"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2943em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])])])])])],-1),y=s("h3",{id:"_8-3-ポイント-2-の方程式を減らすために",tabindex:"-1"},[a("8.3: ポイント 2 の方程式を減らすために "),s("a",{class:"header-anchor",href:"#_8-3-ポイント-2-の方程式を減らすために","aria-label":'Permalink to "8.3: ポイント 2 の方程式を減らすために"'},"​")],-1),v=s("ol",{start:"3"},[s("li",null,[a("ポイント 2 の方程式を減らすために: 節点電位法. ルー プ電流法. 等価回路 (3 端子の場合 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"⇒"),s("mi",{mathvariant:"normal"},"△"),s("mtext",null,"又")]),s("annotation",{encoding:"application/x-tex"},"\\Rightarrow \\triangle 又")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"⇒"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"△"),s("span",{class:"mord cjk_fallback"},"又")])])]),a(" 又 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Y")]),s("annotation",{encoding:"application/x-tex"},"Y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"Y")])])]),a(" の形, 起電力のある 2 端子の場合 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"⇒")]),s("annotation",{encoding:"application/x-tex"},"\\Rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"⇒")])])]),a(" 抵抗と電池の直列)")])],-1),x=r('

    8.4: 無限につながる抵抗

    1. 無限につながる抵抗 : 無限に続く格子の隣り合う節点 間で,自己相似性を使う。鏡像法の一般化された方法.

    8.5: 交流回路

    ',3),w=s("ol",{start:"5"},[s("li",null,[a("交流回路: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),a(" を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Z")]),s("annotation",{encoding:"application/x-tex"},"Z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z")])])]),a(" に置き換えてポイント "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"∼"),s("mn",null,"4")]),s("annotation",{encoding:"application/x-tex"},"1 \\sim 4")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∼"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"4")])])]),a(" を用 いる."),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("msub",null,[s("mi",null,"Z"),s("mi",null,"R")]),s("mo",null,"="),s("mi",null,"R"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"Z"),s("mi",null,"C")]),s("mo",null,"="),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"i"),s("mi",null,"ω"),s("mi",null,"C"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"Z"),s("mi",null,"L")]),s("mo",null,"="),s("mi",null,"i"),s("mi",null,"ω"),s("mi",null,"L")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"φ"),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"Z"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"V"),s("mtext",null,"eff ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"Z"),s("mi",{mathvariant:"normal"},"∣"),s("msub",null,[s("mi",null,"I"),s("mtext",null,"eff ")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"P"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"V"),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"Z"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mo",null,"∑"),s("msubsup",null,[s("mi",null,"I"),s("mi",null,"i"),s("mn",null,"2")]),s("msub",null,[s("mi",null,"R"),s("mi",null,"i")])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} Z_R=R, Z_C=1 / i \\omega C, Z_L=i \\omega L \\\\ \\varphi=\\arg Z, V_{\\text {eff }}=|Z| I_{\\text {eff }} \\\\ P=|V||I| \\cos (\\arg Z)=\\sum I_i^2 R_i \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"4.9em","vertical-align":"-2.2em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.7em"}},[s("span",{style:{top:"-4.91em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω"),s("span",{class:"mord mathnormal"},"L")])]),s("span",{style:{top:"-3.41em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3361em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.2222em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"eff ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3361em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"eff ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-1.7em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},"∣∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.2em"}},[s("span")])])])])])])])])])])])])],-1),b=s("h3",{id:"_8-6-特性時間",tabindex:"-1"},[a("8.6: 特性時間 "),s("a",{class:"header-anchor",href:"#_8-6-特性時間","aria-label":'Permalink to "8.6: 特性時間"'},"​")],-1),k=s("ol",{start:"6"},[s("li",null,[a("特性時間: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"τ"),s("mrow",null,[s("mi",null,"R"),s("mi",null,"C")])]),s("mo",null,"="),s("mi",null,"R"),s("mi",null,"C"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"τ"),s("mrow",null,[s("mi",null,"L"),s("mi",null,"R")])]),s("mo",null,"="),s("mi",null,"L"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R"),s("mi",{mathvariant:"normal"},"."),s("msub",null,[s("mi",null,"ω"),s("mrow",null,[s("mi",null,"L"),s("mi",null,"C")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\tau_{R C}=R C, \\tau_{L R}=L / R . \\omega_{L C}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1132em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"RC")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"RC"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1132em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mord"},"."),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mi",null,"L"),s("mi",null,"C")])])]),s("annotation",{encoding:"application/x-tex"},"1 / \\sqrt{L C}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1767em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9267em"}},[s("span",{class:"svg-align",style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{"padding-left":"0.833em"}},[s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C")])]),s("span",{style:{top:"-2.8867em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"hide-tail",style:{"min-width":"0.853em",height:"1.08em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.08em",viewBox:"0 0 400000 1080",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M95,702 +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const F=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 8","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/8.md","filePath":"academic/physics/ipho-formulas-jpn/8.md","lastUpdated":1699051935000}'),p={name:"academic/physics/ipho-formulas-jpn/8.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-8",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 8 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-8","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 8"'},"​")],-1),h=s("h2",{id:"_8-電気回路",tabindex:"-1"},[a("8: 電気回路 "),s("a",{class:"header-anchor",href:"#_8-電気回路","aria-label":'Permalink to "8: 電気回路"'},"​")],-1),o=s("h3",{id:"_8-1-v-i-r-p-v-i",tabindex:"-1"},[a("8.1: V=I R, P=V I "),s("a",{class:"header-anchor",href:"#_8-1-v-i-r-p-v-i","aria-label":'Permalink to "8.1: V=I R, P=V I"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"V"),s("mo",null,"="),s("mi",null,"I"),s("mi",null,"R"),s("mo",{separator:"true"},","),s("mi",null,"P"),s("mo",null,"="),s("mi",null,"V"),s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"V=I R, P=V I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"R"),s("mtext",null,"直列 ")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"R"),s("mi",null,"i")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"R"),s("mtext",null,"並列 "),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"="),s("mo",null,"∑"),s("msubsup",null,[s("mi",null,"R"),s("mi",null,"i"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])]),s("annotation",{encoding:"application/x-tex"},"R_{\\text {直列 }}=\\sum R_i, R_{\\text {並列 }}^{-1}=\\sum R_i^{-1} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"直列"),s("span",{class:"mord mtight"}," ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.4163em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"並列"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2837em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.433em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.267em"}},[s("span")])])])])])])])])])])])],-1),u=s("h3",{id:"_8-2-kirchhoff-の法則",tabindex:"-1"},[a("8.2: Kirchhoff の法則 "),s("a",{class:"header-anchor",href:"#_8-2-kirchhoff-の法則","aria-label":'Permalink to "8.2: Kirchhoff の法則"'},"​")],-1),d=s("ol",{start:"2"},[s("li",null,[a("Kirchhoff の法則 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("munder",null,[s("mo",null,"∑"),s("mstyle",{scriptlevel:"1"},[s("mtable",{rowspacing:"0.1em",columnalign:"center",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"1",displaystyle:"false"},[s("mtext",null," 節点 ")])])])])])]),s("mi",null,"I"),s("mo",null,"="),s("mn",null,"0"),s("mo",{separator:"true"},","),s("munder",null,[s("mo",null,"∑"),s("mtext",null,"閉路 ")]),s("mi",null,"V"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\sum_{\\substack{\\text { 節点 }}} I=0, \\sum_{\\text {閉路 }} V=0 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4703em","vertical-align":"-1.4203em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.05em"}},[s("span",{style:{top:"-1.8568em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6817em"}},[s("span",{style:{top:"-2.6983em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"}," "),s("span",{class:"mord cjk_fallback mtight"},"節点"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1817em"}},[s("span")])])])])])])])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.4203em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.3443em","vertical-align":"-1.2943em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.05em"}},[s("span",{style:{top:"-1.8557em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"閉路"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2943em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])])])])])],-1),y=s("h3",{id:"_8-3-ポイント-2-の方程式を減らすために",tabindex:"-1"},[a("8.3: ポイント 2 の方程式を減らすために "),s("a",{class:"header-anchor",href:"#_8-3-ポイント-2-の方程式を減らすために","aria-label":'Permalink to "8.3: ポイント 2 の方程式を減らすために"'},"​")],-1),v=s("ol",{start:"3"},[s("li",null,[a("ポイント 2 の方程式を減らすために: 節点電位法. ルー プ電流法. 等価回路 (3 端子の場合 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"⇒"),s("mi",{mathvariant:"normal"},"△"),s("mtext",null,"又")]),s("annotation",{encoding:"application/x-tex"},"\\Rightarrow \\triangle 又")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"⇒"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"△"),s("span",{class:"mord cjk_fallback"},"又")])])]),a(" 又 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Y")]),s("annotation",{encoding:"application/x-tex"},"Y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"Y")])])]),a(" の形, 起電力のある 2 端子の場合 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"⇒")]),s("annotation",{encoding:"application/x-tex"},"\\Rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"⇒")])])]),a(" 抵抗と電池の直列)")])],-1),x=r('

    8.4: 無限につながる抵抗

    1. 無限につながる抵抗 : 無限に続く格子の隣り合う節点 間で,自己相似性を使う。鏡像法の一般化された方法.

    8.5: 交流回路

    ',3),w=s("ol",{start:"5"},[s("li",null,[a("交流回路: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),a(" を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Z")]),s("annotation",{encoding:"application/x-tex"},"Z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z")])])]),a(" に置き換えてポイント "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"∼"),s("mn",null,"4")]),s("annotation",{encoding:"application/x-tex"},"1 \\sim 4")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∼"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"4")])])]),a(" を用 いる."),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("msub",null,[s("mi",null,"Z"),s("mi",null,"R")]),s("mo",null,"="),s("mi",null,"R"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"Z"),s("mi",null,"C")]),s("mo",null,"="),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"i"),s("mi",null,"ω"),s("mi",null,"C"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"Z"),s("mi",null,"L")]),s("mo",null,"="),s("mi",null,"i"),s("mi",null,"ω"),s("mi",null,"L")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"φ"),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"Z"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"V"),s("mtext",null,"eff ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"Z"),s("mi",{mathvariant:"normal"},"∣"),s("msub",null,[s("mi",null,"I"),s("mtext",null,"eff ")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"P"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"V"),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"Z"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mo",null,"∑"),s("msubsup",null,[s("mi",null,"I"),s("mi",null,"i"),s("mn",null,"2")]),s("msub",null,[s("mi",null,"R"),s("mi",null,"i")])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} Z_R=R, Z_C=1 / i \\omega C, Z_L=i \\omega L \\\\ \\varphi=\\arg Z, V_{\\text {eff }}=|Z| I_{\\text {eff }} \\\\ P=|V||I| \\cos (\\arg Z)=\\sum I_i^2 R_i \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"4.9em","vertical-align":"-2.2em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.7em"}},[s("span",{style:{top:"-4.91em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω"),s("span",{class:"mord mathnormal"},"L")])]),s("span",{style:{top:"-3.41em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3361em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.2222em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"eff ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3361em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"eff ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-1.7em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},"∣∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.2em"}},[s("span")])])])])])])])])])])])])],-1),b=s("h3",{id:"_8-6-特性時間",tabindex:"-1"},[a("8.6: 特性時間 "),s("a",{class:"header-anchor",href:"#_8-6-特性時間","aria-label":'Permalink to "8.6: 特性時間"'},"​")],-1),k=s("ol",{start:"6"},[s("li",null,[a("特性時間: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"τ"),s("mrow",null,[s("mi",null,"R"),s("mi",null,"C")])]),s("mo",null,"="),s("mi",null,"R"),s("mi",null,"C"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"τ"),s("mrow",null,[s("mi",null,"L"),s("mi",null,"R")])]),s("mo",null,"="),s("mi",null,"L"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R"),s("mi",{mathvariant:"normal"},"."),s("msub",null,[s("mi",null,"ω"),s("mrow",null,[s("mi",null,"L"),s("mi",null,"C")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\tau_{R C}=R C, \\tau_{L R}=L / R . \\omega_{L C}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1132em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"RC")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"RC"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1132em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mord"},"."),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mi",null,"L"),s("mi",null,"C")])])]),s("annotation",{encoding:"application/x-tex"},"1 / \\sqrt{L C}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1767em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9267em"}},[s("span",{class:"svg-align",style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{"padding-left":"0.833em"}},[s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C")])]),s("span",{style:{top:"-2.8867em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"hide-tail",style:{"min-width":"0.853em",height:"1.08em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.08em",viewBox:"0 0 400000 1080",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M95,702 c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14 c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54 c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10 diff --git a/assets/academic_physics_ipho-formulas-jpn_8.md.f1df91b7.lean.js b/assets/academic_physics_ipho-formulas-jpn_8.md.f05c02fb.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_8.md.f1df91b7.lean.js rename to assets/academic_physics_ipho-formulas-jpn_8.md.f05c02fb.lean.js index d3d4f517..1c70c580 100644 --- a/assets/academic_physics_ipho-formulas-jpn_8.md.f1df91b7.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_8.md.f05c02fb.lean.js @@ -1,4 +1,4 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const F=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 8","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/8.md","filePath":"academic/physics/ipho-formulas-jpn/8.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/8.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-8",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 8 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-8","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 8"'},"​")],-1),h=s("h2",{id:"_8-電気回路",tabindex:"-1"},[a("8: 電気回路 "),s("a",{class:"header-anchor",href:"#_8-電気回路","aria-label":'Permalink to "8: 電気回路"'},"​")],-1),o=s("h3",{id:"_8-1-v-i-r-p-v-i",tabindex:"-1"},[a("8.1: V=I R, P=V I "),s("a",{class:"header-anchor",href:"#_8-1-v-i-r-p-v-i","aria-label":'Permalink to "8.1: V=I R, P=V I"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"V"),s("mo",null,"="),s("mi",null,"I"),s("mi",null,"R"),s("mo",{separator:"true"},","),s("mi",null,"P"),s("mo",null,"="),s("mi",null,"V"),s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"V=I R, P=V I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"R"),s("mtext",null,"直列 ")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"R"),s("mi",null,"i")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"R"),s("mtext",null,"並列 "),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"="),s("mo",null,"∑"),s("msubsup",null,[s("mi",null,"R"),s("mi",null,"i"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])]),s("annotation",{encoding:"application/x-tex"},"R_{\\text {直列 }}=\\sum R_i, R_{\\text {並列 }}^{-1}=\\sum R_i^{-1} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"直列"),s("span",{class:"mord mtight"}," ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.4163em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"並列"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2837em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.433em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.267em"}},[s("span")])])])])])])])])])])])],-1),u=s("h3",{id:"_8-2-kirchhoff-の法則",tabindex:"-1"},[a("8.2: Kirchhoff の法則 "),s("a",{class:"header-anchor",href:"#_8-2-kirchhoff-の法則","aria-label":'Permalink to "8.2: Kirchhoff の法則"'},"​")],-1),d=s("ol",{start:"2"},[s("li",null,[a("Kirchhoff の法則 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("munder",null,[s("mo",null,"∑"),s("mstyle",{scriptlevel:"1"},[s("mtable",{rowspacing:"0.1em",columnalign:"center",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"1",displaystyle:"false"},[s("mtext",null," 節点 ")])])])])])]),s("mi",null,"I"),s("mo",null,"="),s("mn",null,"0"),s("mo",{separator:"true"},","),s("munder",null,[s("mo",null,"∑"),s("mtext",null,"閉路 ")]),s("mi",null,"V"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\sum_{\\substack{\\text { 節点 }}} I=0, \\sum_{\\text {閉路 }} V=0 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4703em","vertical-align":"-1.4203em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.05em"}},[s("span",{style:{top:"-1.8568em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6817em"}},[s("span",{style:{top:"-2.6983em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"}," "),s("span",{class:"mord cjk_fallback mtight"},"節点"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1817em"}},[s("span")])])])])])])])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.4203em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.3443em","vertical-align":"-1.2943em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.05em"}},[s("span",{style:{top:"-1.8557em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"閉路"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2943em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])])])])])],-1),y=s("h3",{id:"_8-3-ポイント-2-の方程式を減らすために",tabindex:"-1"},[a("8.3: ポイント 2 の方程式を減らすために "),s("a",{class:"header-anchor",href:"#_8-3-ポイント-2-の方程式を減らすために","aria-label":'Permalink to "8.3: ポイント 2 の方程式を減らすために"'},"​")],-1),v=s("ol",{start:"3"},[s("li",null,[a("ポイント 2 の方程式を減らすために: 節点電位法. ルー プ電流法. 等価回路 (3 端子の場合 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"⇒"),s("mi",{mathvariant:"normal"},"△"),s("mtext",null,"又")]),s("annotation",{encoding:"application/x-tex"},"\\Rightarrow \\triangle 又")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"⇒"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"△"),s("span",{class:"mord cjk_fallback"},"又")])])]),a(" 又 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Y")]),s("annotation",{encoding:"application/x-tex"},"Y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"Y")])])]),a(" の形, 起電力のある 2 端子の場合 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"⇒")]),s("annotation",{encoding:"application/x-tex"},"\\Rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"⇒")])])]),a(" 抵抗と電池の直列)")])],-1),x=r("",3),w=s("ol",{start:"5"},[s("li",null,[a("交流回路: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),a(" を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Z")]),s("annotation",{encoding:"application/x-tex"},"Z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z")])])]),a(" に置き換えてポイント "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"∼"),s("mn",null,"4")]),s("annotation",{encoding:"application/x-tex"},"1 \\sim 4")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∼"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"4")])])]),a(" を用 いる."),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("msub",null,[s("mi",null,"Z"),s("mi",null,"R")]),s("mo",null,"="),s("mi",null,"R"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"Z"),s("mi",null,"C")]),s("mo",null,"="),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"i"),s("mi",null,"ω"),s("mi",null,"C"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"Z"),s("mi",null,"L")]),s("mo",null,"="),s("mi",null,"i"),s("mi",null,"ω"),s("mi",null,"L")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"φ"),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"Z"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"V"),s("mtext",null,"eff ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"Z"),s("mi",{mathvariant:"normal"},"∣"),s("msub",null,[s("mi",null,"I"),s("mtext",null,"eff ")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"P"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"V"),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"Z"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mo",null,"∑"),s("msubsup",null,[s("mi",null,"I"),s("mi",null,"i"),s("mn",null,"2")]),s("msub",null,[s("mi",null,"R"),s("mi",null,"i")])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} Z_R=R, Z_C=1 / i \\omega C, Z_L=i \\omega L \\\\ \\varphi=\\arg Z, V_{\\text {eff }}=|Z| I_{\\text {eff }} \\\\ P=|V||I| \\cos (\\arg Z)=\\sum I_i^2 R_i \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"4.9em","vertical-align":"-2.2em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.7em"}},[s("span",{style:{top:"-4.91em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω"),s("span",{class:"mord mathnormal"},"L")])]),s("span",{style:{top:"-3.41em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3361em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.2222em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"eff ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3361em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"eff ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-1.7em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},"∣∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.2em"}},[s("span")])])])])])])])])])])])])],-1),b=s("h3",{id:"_8-6-特性時間",tabindex:"-1"},[a("8.6: 特性時間 "),s("a",{class:"header-anchor",href:"#_8-6-特性時間","aria-label":'Permalink to "8.6: 特性時間"'},"​")],-1),k=s("ol",{start:"6"},[s("li",null,[a("特性時間: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"τ"),s("mrow",null,[s("mi",null,"R"),s("mi",null,"C")])]),s("mo",null,"="),s("mi",null,"R"),s("mi",null,"C"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"τ"),s("mrow",null,[s("mi",null,"L"),s("mi",null,"R")])]),s("mo",null,"="),s("mi",null,"L"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R"),s("mi",{mathvariant:"normal"},"."),s("msub",null,[s("mi",null,"ω"),s("mrow",null,[s("mi",null,"L"),s("mi",null,"C")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\tau_{R C}=R C, \\tau_{L R}=L / R . \\omega_{L C}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1132em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"RC")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"RC"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1132em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mord"},"."),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mi",null,"L"),s("mi",null,"C")])])]),s("annotation",{encoding:"application/x-tex"},"1 / \\sqrt{L C}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1767em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9267em"}},[s("span",{class:"svg-align",style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{"padding-left":"0.833em"}},[s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C")])]),s("span",{style:{top:"-2.8867em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"hide-tail",style:{"min-width":"0.853em",height:"1.08em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.08em",viewBox:"0 0 400000 1080",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M95,702 +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as m,c as e,H as i,k as s,a,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const F=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 8","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/8.md","filePath":"academic/physics/ipho-formulas-jpn/8.md","lastUpdated":1699051935000}'),p={name:"academic/physics/ipho-formulas-jpn/8.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-8",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 8 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-8","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 8"'},"​")],-1),h=s("h2",{id:"_8-電気回路",tabindex:"-1"},[a("8: 電気回路 "),s("a",{class:"header-anchor",href:"#_8-電気回路","aria-label":'Permalink to "8: 電気回路"'},"​")],-1),o=s("h3",{id:"_8-1-v-i-r-p-v-i",tabindex:"-1"},[a("8.1: V=I R, P=V I "),s("a",{class:"header-anchor",href:"#_8-1-v-i-r-p-v-i","aria-label":'Permalink to "8.1: V=I R, P=V I"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"V"),s("mo",null,"="),s("mi",null,"I"),s("mi",null,"R"),s("mo",{separator:"true"},","),s("mi",null,"P"),s("mo",null,"="),s("mi",null,"V"),s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"V=I R, P=V I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"R"),s("mtext",null,"直列 ")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"R"),s("mi",null,"i")]),s("mo",{separator:"true"},","),s("msubsup",null,[s("mi",null,"R"),s("mtext",null,"並列 "),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"="),s("mo",null,"∑"),s("msubsup",null,[s("mi",null,"R"),s("mi",null,"i"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])]),s("annotation",{encoding:"application/x-tex"},"R_{\\text {直列 }}=\\sum R_i, R_{\\text {並列 }}^{-1}=\\sum R_i^{-1} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"直列"),s("span",{class:"mord mtight"}," ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.4163em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"並列"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2837em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.433em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.267em"}},[s("span")])])])])])])])])])])])],-1),u=s("h3",{id:"_8-2-kirchhoff-の法則",tabindex:"-1"},[a("8.2: Kirchhoff の法則 "),s("a",{class:"header-anchor",href:"#_8-2-kirchhoff-の法則","aria-label":'Permalink to "8.2: Kirchhoff の法則"'},"​")],-1),d=s("ol",{start:"2"},[s("li",null,[a("Kirchhoff の法則 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("munder",null,[s("mo",null,"∑"),s("mstyle",{scriptlevel:"1"},[s("mtable",{rowspacing:"0.1em",columnalign:"center",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"1",displaystyle:"false"},[s("mtext",null," 節点 ")])])])])])]),s("mi",null,"I"),s("mo",null,"="),s("mn",null,"0"),s("mo",{separator:"true"},","),s("munder",null,[s("mo",null,"∑"),s("mtext",null,"閉路 ")]),s("mi",null,"V"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\sum_{\\substack{\\text { 節点 }}} I=0, \\sum_{\\text {閉路 }} V=0 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4703em","vertical-align":"-1.4203em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.05em"}},[s("span",{style:{top:"-1.8568em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6817em"}},[s("span",{style:{top:"-2.6983em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"}," "),s("span",{class:"mord cjk_fallback mtight"},"節点"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1817em"}},[s("span")])])])])])])])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.4203em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.3443em","vertical-align":"-1.2943em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.05em"}},[s("span",{style:{top:"-1.8557em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord cjk_fallback mtight"},"閉路"),s("span",{class:"mord mtight"}," ")])])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2943em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])])])])])],-1),y=s("h3",{id:"_8-3-ポイント-2-の方程式を減らすために",tabindex:"-1"},[a("8.3: ポイント 2 の方程式を減らすために "),s("a",{class:"header-anchor",href:"#_8-3-ポイント-2-の方程式を減らすために","aria-label":'Permalink to "8.3: ポイント 2 の方程式を減らすために"'},"​")],-1),v=s("ol",{start:"3"},[s("li",null,[a("ポイント 2 の方程式を減らすために: 節点電位法. ルー プ電流法. 等価回路 (3 端子の場合 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"⇒"),s("mi",{mathvariant:"normal"},"△"),s("mtext",null,"又")]),s("annotation",{encoding:"application/x-tex"},"\\Rightarrow \\triangle 又")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"⇒"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"△"),s("span",{class:"mord cjk_fallback"},"又")])])]),a(" 又 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Y")]),s("annotation",{encoding:"application/x-tex"},"Y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"Y")])])]),a(" の形, 起電力のある 2 端子の場合 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"⇒")]),s("annotation",{encoding:"application/x-tex"},"\\Rightarrow")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.3669em"}}),s("span",{class:"mrel"},"⇒")])])]),a(" 抵抗と電池の直列)")])],-1),x=r("",3),w=s("ol",{start:"5"},[s("li",null,[a("交流回路: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),a(" を "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Z")]),s("annotation",{encoding:"application/x-tex"},"Z")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z")])])]),a(" に置き換えてポイント "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mo",null,"∼"),s("mn",null,"4")]),s("annotation",{encoding:"application/x-tex"},"1 \\sim 4")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∼"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"4")])])]),a(" を用 いる."),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mtable",{rowspacing:"0.25em",columnalign:"center",columnspacing:"0em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("msub",null,[s("mi",null,"Z"),s("mi",null,"R")]),s("mo",null,"="),s("mi",null,"R"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"Z"),s("mi",null,"C")]),s("mo",null,"="),s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"i"),s("mi",null,"ω"),s("mi",null,"C"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"Z"),s("mi",null,"L")]),s("mo",null,"="),s("mi",null,"i"),s("mi",null,"ω"),s("mi",null,"L")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"φ"),s("mo",null,"="),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"Z"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"V"),s("mtext",null,"eff ")]),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"Z"),s("mi",{mathvariant:"normal"},"∣"),s("msub",null,[s("mi",null,"I"),s("mtext",null,"eff ")])])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"true"},[s("mrow",null,[s("mi",null,"P"),s("mo",null,"="),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"V"),s("mi",{mathvariant:"normal"},"∣"),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"∣"),s("mi",null,"cos"),s("mo",null,"⁡"),s("mo",{stretchy:"false"},"("),s("mi",null,"arg"),s("mo",null,"⁡"),s("mi",null,"Z"),s("mo",{stretchy:"false"},")"),s("mo",null,"="),s("mo",null,"∑"),s("msubsup",null,[s("mi",null,"I"),s("mi",null,"i"),s("mn",null,"2")]),s("msub",null,[s("mi",null,"R"),s("mi",null,"i")])])])])])]),s("annotation",{encoding:"application/x-tex"},"\\begin{gathered} Z_R=R, Z_C=1 / i \\omega C, Z_L=i \\omega L \\\\ \\varphi=\\arg Z, V_{\\text {eff }}=|Z| I_{\\text {eff }} \\\\ P=|V||I| \\cos (\\arg Z)=\\sum I_i^2 R_i \\end{gathered} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"4.9em","vertical-align":"-2.2em"}}),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.7em"}},[s("span",{style:{top:"-4.91em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0715em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"iω"),s("span",{class:"mord mathnormal"},"L")])]),s("span",{style:{top:"-3.41em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3361em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.2222em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"eff ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mord"},"∣"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3361em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord text mtight"},[s("span",{class:"mord mtight"},"eff ")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])]),s("span",{style:{top:"-1.7em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"P"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V"),s("span",{class:"mord"},"∣∣"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},"∣"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},"cos"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("ar"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"Z"),s("span",{class:"mclose"},")"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8641em"}},[s("span",{style:{top:"-2.453em","margin-left":"-0.0785em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])]),s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.247em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0077em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"2.2em"}},[s("span")])])])])])])])])])])])])],-1),b=s("h3",{id:"_8-6-特性時間",tabindex:"-1"},[a("8.6: 特性時間 "),s("a",{class:"header-anchor",href:"#_8-6-特性時間","aria-label":'Permalink to "8.6: 特性時間"'},"​")],-1),k=s("ol",{start:"6"},[s("li",null,[a("特性時間: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"τ"),s("mrow",null,[s("mi",null,"R"),s("mi",null,"C")])]),s("mo",null,"="),s("mi",null,"R"),s("mi",null,"C"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"τ"),s("mrow",null,[s("mi",null,"L"),s("mi",null,"R")])]),s("mo",null,"="),s("mi",null,"L"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R"),s("mi",{mathvariant:"normal"},"."),s("msub",null,[s("mi",null,"ω"),s("mrow",null,[s("mi",null,"L"),s("mi",null,"C")])]),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"\\tau_{R C}=R C, \\tau_{L R}=L / R . \\omega_{L C}=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1132em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"RC")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"RC"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.1132em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mord"},"."),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3283em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"L"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07153em"}},"C")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("mi",{mathvariant:"normal"},"/"),s("msqrt",null,[s("mrow",null,[s("mi",null,"L"),s("mi",null,"C")])])]),s("annotation",{encoding:"application/x-tex"},"1 / \\sqrt{L C}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1767em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1/"),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9267em"}},[s("span",{class:"svg-align",style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{"padding-left":"0.833em"}},[s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C")])]),s("span",{style:{top:"-2.8867em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"hide-tail",style:{"min-width":"0.853em",height:"1.08em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.08em",viewBox:"0 0 400000 1080",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M95,702 c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14 c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54 c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10 diff --git a/assets/academic_physics_ipho-formulas-jpn_9.md.da4d857a.js b/assets/academic_physics_ipho-formulas-jpn_9.md.083302ab.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_9.md.da4d857a.js rename to assets/academic_physics_ipho-formulas-jpn_9.md.083302ab.js index 0376888b..840dcdbc 100644 --- a/assets/academic_physics_ipho-formulas-jpn_9.md.da4d857a.js +++ b/assets/academic_physics_ipho-formulas-jpn_9.md.083302ab.js @@ -1 +1 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as e,c as i,H as r,k as s,a,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const ns=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 9","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/9.md","filePath":"academic/physics/ipho-formulas-jpn/9.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/9.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-9",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 9 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-9","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 9"'},"​")],-1),h=s("h2",{id:"_9-電磁気学",tabindex:"-1"},[a("9: 電磁気学 "),s("a",{class:"header-anchor",href:"#_9-電磁気学","aria-label":'Permalink to "9: 電磁気学"'},"​")],-1),o=s("h3",{id:"_9-1-coulomb-の法則",tabindex:"-1"},[a("9.1: Coulomb の法則 "),s("a",{class:"header-anchor",href:"#_9-1-coulomb-の法則","aria-label":'Permalink to "9.1: Coulomb の法則"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("mi",null,"k"),s("msub",null,[s("mi",null,"q"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"q"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"U"),s("mo",null,"="),s("mi",null,"k"),s("msub",null,[s("mi",null,"q"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"q"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"F=k q_1 q_2 / r^2, U=k q_1 q_2 / r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" で, Kepler の法則が 使える ("),s("a",{href:"./12"},"Section 12 参照"),a(").")])],-1),d=s("h3",{id:"_9-2-gauss-の法則",tabindex:"-1"},[a("9.2: Gauss の法則 "),s("a",{class:"header-anchor",href:"#_9-2-gauss-の法則","aria-label":'Permalink to "9.2: Gauss の法則"'},"​")],-1),u=s("ol",{start:"2"},[s("li",null,[s("p",null,[a("Gauss の法則 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"S"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\oint \\boldsymbol{B} \\cdot \\mathrm{d} \\boldsymbol{S}=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1111em","vertical-align":"-0.3061em"}}),s("span",{class:"mop op-symbol small-op",style:{"margin-right":"0.19445em",position:"relative",top:"-0.0006em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(",")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∮"),s("mi",null,"ε"),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"S"),s("mo",null,"="),s("mi",null,"Q"),s("mo",{separator:"true"},","),s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"g"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"S"),s("mo",null,"="),s("mo",null,"−"),s("mn",null,"4"),s("mi",null,"π"),s("mi",null,"G"),s("mi",null,"M")]),s("annotation",{encoding:"application/x-tex"},"\\oint \\varepsilon \\boldsymbol{E} \\cdot \\mathrm{d} \\boldsymbol{S}=Q, \\oint \\boldsymbol{g} \\cdot \\mathrm{d} \\boldsymbol{S}=-4 \\pi G M ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mord mathnormal"},"Q"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"g")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM")])])])])])])],-1),y=s("h3",{id:"_9-3-循環定理",tabindex:"-1"},[a("9.3: 循環定理 "),s("a",{class:"header-anchor",href:"#_9-3-循環定理","aria-label":'Permalink to "9.3: 循環定理"'},"​")],-1),b=s("ol",{start:"3"},[s("li",null,[s("p",null,"循環定理 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l"),s("mo",null,"="),s("mn",null,"0"),s("mo",{stretchy:"false"},"("),s("mo",null,"="),s("mover",{accent:"true"},[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"˙")]),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mo",null,"∮"),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l")]),s("mi",null,"μ")]),s("mo",null,"="),s("mi",null,"I"),s("mo",{separator:"true"},","),s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"g"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\oint \\boldsymbol{E} \\cdot \\mathrm{d} \\boldsymbol{l}=0(=\\dot{\\Phi}), \\oint \\frac{\\boldsymbol{B} \\cdot \\mathrm{d} \\boldsymbol{l}}{\\mu}=I, \\oint \\boldsymbol{g} \\cdot \\mathrm{d} \\boldsymbol{l}=0 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mopen"},"("),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2519em","vertical-align":"-0.8804em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9202em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},"Φ")]),s("span",{style:{top:"-3.2523em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1389em"}},[s("span",{class:"mord"},"˙")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"μ")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8804em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"g")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])])])])])],-1),v=s("h3",{id:"_9-4-電流素片により生じる磁束密度",tabindex:"-1"},[a("9.4: 電流素片により生じる磁束密度 "),s("a",{class:"header-anchor",href:"#_9-4-電流素片により生じる磁束密度","aria-label":'Permalink to "9.4: 電流素片により生じる磁束密度"'},"​")],-1),x=s("ol",{start:"4"},[s("li",null,[a("電流素片により生じる磁束密度 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"μ"),s("mi",null,"I")]),s("mrow",null,[s("mn",null,"4"),s("mi",null,"π")])]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l"),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"r")])]),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")])]),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{d} \\boldsymbol{B}=\\frac{\\mu I}{4 \\pi} \\frac{\\mathrm{d} \\boldsymbol{l} \\times \\boldsymbol{e}_r}{r^2} . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0574em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3603em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},".")])])])])]),a(" したがって電流 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),a(" が流れる円形回路の中心では "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"μ"),s("mn",null,"0")]),s("mi",null,"I")]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"r")])])]),s("annotation",{encoding:"application/x-tex"},"B=\\frac{\\mu_0 I}{2 r}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2694em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9244em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(".")])],-1),w=s("h3",{id:"_9-5-ローレンツ力",tabindex:"-1"},[a("9.5: ローレンツ力 "),s("a",{class:"header-anchor",href:"#_9-5-ローレンツ力","aria-label":'Permalink to "9.5: ローレンツ力"'},"​")],-1),k=s("ol",{start:"5"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",null,"e"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"+"),s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"I"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"B"),s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}=e(\\boldsymbol{E}+\\boldsymbol{v} \\times \\boldsymbol{B}), \\boldsymbol{F}=\\boldsymbol{I} \\times \\boldsymbol{B} l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"e"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7694em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.07778em"}},"I")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(".")])],-1),_=s("h3",{id:"_9-6-gauss-の定理と循環定理より",tabindex:"-1"},[a("9.6: Gauss の定理と循環定理より "),s("a",{class:"header-anchor",href:"#_9-6-gauss-の定理と循環定理より","aria-label":'Permalink to "9.6: Gauss の定理と循環定理より"'},"​")],-1),z=s("ol",{start:"6"},[s("li",null,[a("Gauss の定理と循環定理より:帯電した導線について "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"σ"),s("mrow",null,[s("mn",null,"2"),s("mi",null,"π"),s("msub",null,[s("mi",null,"ε"),s("mn",null,"0")]),s("mi",null,"r")])])]),s("annotation",{encoding:"application/x-tex"},"E=\\frac{\\sigma}{2 \\pi \\varepsilon_0 r}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1405em","vertical-align":"-0.4451em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"ε"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4451em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(", 電流が流れる導線について "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"μ"),s("mn",null,"0")]),s("mi",null,"I")]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"π"),s("mi",null,"r")])])]),s("annotation",{encoding:"application/x-tex"},"B=\\frac{\\mu_0 I}{2 \\pi r}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2694em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9244em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 帯電した面について "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"σ"),s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mi",null,"ε"),s("mn",null,"0")])])])]),s("annotation",{encoding:"application/x-tex"},"E=\\frac{\\sigma}{2 \\varepsilon_0}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1405em","vertical-align":"-0.4451em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"ε"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4451em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(", 電流が流れる面につい て "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"μ"),s("mn",null,"0")]),s("mi",null,"i")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"B=\\frac{\\mu_0 i}{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2528em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9078em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight"},"i")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 一様に帯電した球殼(又は無限に長い円 筒)の内部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"E=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(", 軸に沿って表面に電流が流れる 円筒の内部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"B=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 密度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ρ")]),s("annotation",{encoding:"application/x-tex"},"\\rho")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ")])])]),a(" で一様に帯電, 又は一様 な電流 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"i")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{i}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6933em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"i")])])])])]),a(" が流れる, 球 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"d"),s("mo",null,"="),s("mn",null,"3"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/")]),s("annotation",{encoding:"application/x-tex"},"(d=3) /")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/")])])]),a(" 円柱 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"d"),s("mo",null,"−"),s("mn",null,"2"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/")]),s("annotation",{encoding:"application/x-tex"},"(d-2) /")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/")])])]),a(" 平面 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"d"),s("mo",null,"="),s("mn",null,"1"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(d=1)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")")])])]),a(" の内部で,"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"ρ"),s("mrow",null,[s("mi",null,"ε"),s("mi",null,"d")])]),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mrow",null,[s("mi",null,"μ"),s("mi",null,"d")])]),s("mi",{mathvariant:"bold-italic"},"i"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"r")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{E}=\\frac{\\rho}{\\varepsilon d} \\boldsymbol{r}, \\boldsymbol{B}=\\frac{1}{\\mu d} \\boldsymbol{i} \\times \\boldsymbol{r} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.7936em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1076em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mord mathnormal"},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2019em","vertical-align":"-0.8804em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord mathnormal"},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8804em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"i")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])])])])])])])])],-1),f=s("h3",{id:"_9-7-長いソレノイド",tabindex:"-1"},[a("9.7: 長いソレノイド "),s("a",{class:"header-anchor",href:"#_9-7-長いソレノイド","aria-label":'Permalink to "9.7: 長いソレノイド"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("長いソレノイド: 内部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mi",null,"μ"),s("mi",null,"n"),s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"B=\\mu n I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),a(", 外部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"B=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 磁束 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"="),s("mi",null,"N"),s("mi",null,"B"),s("mi",null,"S"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"n"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"N"),s("mi",null,"l")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"\\Phi=N B S\\left(n=\\frac{N}{l}\\right)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2223em","vertical-align":"-0.35em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"NBS"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.01968em"}},"l")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"N")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])])])])]),a(". インダクタンス "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"L"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"L=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"I"),s("mo",null,"="),s("mi",null,"μ"),s("msup",null,[s("mi",null,"n"),s("mn",null,"2")]),s("mi",null,"V")]),s("annotation",{encoding:"application/x-tex"},"\\Phi / I=\\mu n^2 V")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V")])])]),a(". 短いソレノイド "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msub",null,[s("mi",null,"B"),s("mi",{mathvariant:"normal"},"∥")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"μ"),s("mi",null,"n"),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"Ω")]),s("mrow",null,[s("mn",null,"4"),s("mi",null,"π")])]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"Ω")]),s("annotation",{encoding:"application/x-tex"},": B_{\\|}=\\frac{\\mu n I \\Omega}{4 \\pi}(\\Omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0385em","vertical-align":"-0.3552em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.5198em","margin-left":"-0.0502em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"∥")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3552em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2694em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9244em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"π")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"mord mathnormal mtight"},"n"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord mtight"},"Ω")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"Ω")])])]),a(" は 立体角).")])],-1),B=s("h3",{id:"_9-8-磁場を小型コイルや衝撃検流計で測定する",tabindex:"-1"},[a("9.8: 磁場を小型コイルや衝撃検流計で測定する "),s("a",{class:"header-anchor",href:"#_9-8-磁場を小型コイルや衝撃検流計で測定する","aria-label":'Permalink to "9.8: 磁場を小型コイルや衝撃検流計で測定する"'},"​")],-1),L=s("ol",{start:"9"},[s("li",null,[a("磁場を小型コイルや衝撃検流計で測定する: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"q"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"q=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∫"),s("mfrac",null,[s("mi",null,"V"),s("mi",null,"R")]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"t"),s("mo",null,"="),s("mi",null,"N"),s("mi",null,"S"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"B"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"\\int \\frac{V}{R} \\mathrm{~d} t=N S \\Delta B / R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2173em","vertical-align":"-0.345em"}}),s("span",{class:"mop op-symbol small-op",style:{"margin-right":"0.19445em",position:"relative",top:"-0.0006em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.22222em"}},"V")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"NS"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),a(".")])],-1),q=s("h3",{id:"_9-9-静電場のエネルギー",tabindex:"-1"},[a("9.9: 静電場のエネルギー "),s("a",{class:"header-anchor",href:"#_9-9-静電場のエネルギー","aria-label":'Permalink to "9.9: 静電場のエネルギー"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("静電場のエネルギー:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mi",null,"k"),s("munder",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"<"),s("mi",null,"j")])]),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"q"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"q"),s("mi",null,"j")])]),s("msub",null,[s("mi",null,"r"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])])]),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mo",null,"∫"),s("mi",null,"ϕ"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"q"),s("mo",{separator:"true"},","),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"q"),s("mo",null,"="),s("mi",null,"ρ"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"V")]),s("annotation",{encoding:"application/x-tex"},"U=k \\sum_{i9.10: 一様に帯電した球面や円筒面の各部分の間に働く力
    1. 一様に帯電した球面や円筒面の各部分の間に働く力 : 帯電による力を静水圧による力に置き換える.

    9.11: 全ての電荷

    ',3),S=s("ol",{start:"12"},[s("li",null,[a("全ての電荷が距離 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" にある場合(例えば,不均一に帯 電した球やリングの中心) "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ϕ"),s("mi",null,"ϕ"),s("mo",null,"="),s("mi",null,"k"),s("mi",null,"Q"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"\\phi \\phi=k Q / r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ϕϕ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord mathnormal"},"Q"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])])])],-1),E=l('

    9.12: 外部電荷

    1. 外部電荷によって引き起こされる正味の電荷(又は電 位)を求めるには, 電荷を「出現」させて問題を対称的 にし,重ね合わせの原理を用いる.

    9.14: 導体

    ',3),F=s("ol",{start:"14"},[s("li",null,[a("導体は電荷や電場を遮蔽する.例えば,中空の球体の 内部の電荷分布は外から見えない(あたかも "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Q")]),s("annotation",{encoding:"application/x-tex"},"Q")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"Q")])])]),a(" という 電荷を持った導電性の球があるように見える).")])],-1),T=s("h3",{id:"_9-15-静電容量",tabindex:"-1"},[a("9.15: 静電容量 "),s("a",{class:"header-anchor",href:"#_9-15-静電容量","aria-label":'Permalink to "9.15: 静電容量"'},"​")],-1),V=s("ol",{start:"15"},[s("li",null,[a("静電容量: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"C"),s("mo",null,"="),s("mi",null,"ε"),s("mi",null,"S"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"C=\\varepsilon S / d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"εS"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d")])])]),a(" (平板), "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"4"),s("mi",null,"π"),s("mi",null,"ε"),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"4 \\pi \\varepsilon r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" (球), "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"π"),s("mi",null,"ε"),s("mi",null,"l"),s("mo",{stretchy:"false"},"("),s("mi",null,"ln"),s("mo",null,"⁡"),s("mi",null,"R"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])]),s("annotation",{encoding:"application/x-tex"},"2 \\pi \\varepsilon l(\\ln R / r)^{-1}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"εl"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},"ln"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])])]),a(" (同軸円筒).")])],-1),N=s("h3",{id:"_9-16-双極子モーメント",tabindex:"-1"},[a("9.16: 双極子モーメント "),s("a",{class:"header-anchor",href:"#_9-16-双極子モーメント","aria-label":'Permalink to "9.16: 双極子モーメント"'},"​")],-1),j=s("ol",{start:"16"},[s("li",null,[s("p",null,"双極子モーメント:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mi",null,"e")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"q"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mo",null,"="),s("mi",null,"q"),s("mi",{mathvariant:"bold-italic"},"d"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mi",null,"μ")]),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"bold-italic"},"S")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{p}_e=\\sum q_i \\boldsymbol{r}_i=q \\boldsymbol{d}, \\boldsymbol{p}_\\mu=I \\boldsymbol{S} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6886em","vertical-align":"-0.2441em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.0573em"}},[s("span",{style:{top:"-2.4559em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"e")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2441em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0747em","vertical-align":"-0.3802em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"d")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.0573em"}},[s("span",{style:{top:"-2.4559em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"μ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3802em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])])])])])])])])],-1),R=s("h3",{id:"_9-17-双極子場",tabindex:"-1"},[a("9.17: 双極子場 "),s("a",{class:"header-anchor",href:"#_9-17-双極子場","aria-label":'Permalink to "9.17: 双極子場"'},"​")],-1),C=s("ol",{start:"17"},[s("li",null,[a("双極子場 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ϕ"),s("mo",null,"="),s("mi",null,"k"),s("mi",{mathvariant:"bold-italic"},"p"),s("mo",null,"⋅"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"r")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"E"),s("mo",{separator:"true"},","),s("mi",null,"B"),s("mo",null,"∝"),s("msup",null,[s("mi",null,"r"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"3")])])]),s("annotation",{encoding:"application/x-tex"},"\\phi=k \\boldsymbol{p} \\cdot \\boldsymbol{e}_r / r^2, E, B \\propto r^{-3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"3")])])])])])])])])])])])])],-1),Q=s("h3",{id:"_9-18-双極子に働く力",tabindex:"-1"},[a("9.18: 双極子に働く力 "),s("a",{class:"header-anchor",href:"#_9-18-双極子に働く力","aria-label":'Permalink to "9.18: 双極子に働く力"'},"​")],-1),A=s("ol",{start:"19"},[s("li",null,[a("双極子に働く力 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mi",null,"e")]),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",{fence:"true"},")")]),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",{separator:"true"},","),s("mi",null,"F"),s("mo",null,"="),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mi",null,"μ")]),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",{fence:"true"},")")]),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),s("annotation",{encoding:"application/x-tex"},"F=\\left(\\boldsymbol{p}_e \\cdot \\boldsymbol{E}\\right)^{\\prime}, F=\\left(\\boldsymbol{p}_\\mu \\cdot \\boldsymbol{B}\\right)^{\\prime}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1418em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.0573em"}},[s("span",{style:{top:"-2.4559em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"e")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2441em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8918em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.372em","vertical-align":"-0.3802em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.0573em"}},[s("span",{style:{top:"-2.4559em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"μ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3802em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9918em"}},[s("span",{style:{top:"-3.3029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])])])])]),a(" [訳 者注 : ここの微分はむしろ "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"grad"),s("mo",null,"⁡")]),s("annotation",{encoding:"application/x-tex"},"\\operatorname{grad}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"grad")])])])]),a(" である]. 2 つの双極 子間の相互作用 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("mi",null,"F"),s("mo",null,"∝"),s("msup",null,[s("mi",null,"r"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])])]),s("annotation",{encoding:"application/x-tex"},": F \\propto r^{-4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])])])])]),a(".")])],-1),G=s("h3",{id:"_9-19-磁気双極子としての点電荷",tabindex:"-1"},[a("9.19: 磁気双極子としての点電荷 "),s("a",{class:"header-anchor",href:"#_9-19-磁気双極子としての点電荷","aria-label":'Permalink to "9.19: 磁気双極子としての点電荷"'},"​")],-1),U=s("ol",{start:"19"},[s("li",null,[a("磁気双極子としての点電荷 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"p"),s("mi",null,"μ")]),s("mo",null,"∝"),s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"∝"),s("msubsup",null,[s("mi",null,"v"),s("mo",{lspace:"0em",rspace:"0em"},"⊥"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"p_\\mu \\propto \\Phi \\propto v_{\\perp}^2 / B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7167em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"μ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0972em","vertical-align":"-0.2831em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-2.4169em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"⊥")])])]),s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2831em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" は断熱 不変量 ("),s("a",{href:"./4#_4-22-断熱不変量"},"Section 4: #22"),a(" 参照).")])],-1),O=l('

    9.20: 鏡像法

    1. 鏡像法 : 接地された(磁石の場合は超電導の)平面が鏡 の役割をする. 接地された(又は孤立した)球体の場 は, 球体の内部にある 1 つ(又は 2 つ)の架空の電荷 のつくる場として求められる. 平面導波管(金属板の 間のスリット)内の場は, 電磁平面波の重ね合わせと して求められる.

    9.21: 一様(電)場中の球 (円柱) の分極

    ',3),D=s("ol",{start:"21"},[s("li",null,[a("一様(電)場中の球 (円柱) の分極 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mo",null,"+"),s("mi",null,"ρ")]),s("annotation",{encoding:"application/x-tex"},"(+\\rho")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"+"),s("span",{class:"mord mathnormal"},"ρ")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"−"),s("mi",null,"ρ")]),s("annotation",{encoding:"application/x-tex"},"-\\rho")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal"},"ρ")])])]),a(" に一 様に帯電した球 (円柱) の重ね合わせで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d"),s("mo",null,"∝"),s("mi",null,"E")]),s("annotation",{encoding:"application/x-tex"},"d \\propto E")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E")])])]),a(".")])],-1),$=s("h3",{id:"_9-22-渦電流",tabindex:"-1"},[a("9.22: 渦電流 "),s("a",{class:"header-anchor",href:"#_9-22-渦電流","aria-label":'Permalink to "9.22: 渦電流"'},"​")],-1),H=s("ol",{start:"22"},[s("li",null,[a("渦電流: 電流損失密度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"≈"),s("msup",null,[s("mi",null,"B"),s("mn",null,"2")]),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"ρ"),s("mi",{mathvariant:"normal"},"."),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"\\approx B^2 v^2 / \\rho .1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4831em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mord"},".1")])])]),a(" 回の通過で与え られる運動量 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mi",null,"τ"),s("mo",null,"≈"),s("msup",null,[s("mi",null,"B"),s("mn",null,"2")]),s("msup",null,[s("mi",null,"a"),s("mn",null,"3")]),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"ρ")]),s("annotation",{encoding:"application/x-tex"},"F \\tau \\approx B^2 a^3 d / \\rho")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])])])])])]),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"ρ")])])]),a(" (ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" は厚さ, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(" は大きさ).")])],-1);function J(K,W,X,Y,Z,ss){const t=n;return e(),i("div",null,[c,r(t,{readTime:"4",words:"950"}),h,o,g,d,u,y,b,v,x,w,k,_,z,f,M,B,L,q,I,P,S,E,F,T,V,N,j,R,C,Q,A,G,U,O,D,$,H])}const ms=m(p,[["render",J]]);export{ns as __pageData,ms as default}; +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as e,c as i,H as r,k as s,a,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const ns=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 9","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/9.md","filePath":"academic/physics/ipho-formulas-jpn/9.md","lastUpdated":1699051935000}'),p={name:"academic/physics/ipho-formulas-jpn/9.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-9",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 9 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-9","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 9"'},"​")],-1),h=s("h2",{id:"_9-電磁気学",tabindex:"-1"},[a("9: 電磁気学 "),s("a",{class:"header-anchor",href:"#_9-電磁気学","aria-label":'Permalink to "9: 電磁気学"'},"​")],-1),o=s("h3",{id:"_9-1-coulomb-の法則",tabindex:"-1"},[a("9.1: Coulomb の法則 "),s("a",{class:"header-anchor",href:"#_9-1-coulomb-の法則","aria-label":'Permalink to "9.1: Coulomb の法則"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("mi",null,"k"),s("msub",null,[s("mi",null,"q"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"q"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"U"),s("mo",null,"="),s("mi",null,"k"),s("msub",null,[s("mi",null,"q"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"q"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"F=k q_1 q_2 / r^2, U=k q_1 q_2 / r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" で, Kepler の法則が 使える ("),s("a",{href:"./12"},"Section 12 参照"),a(").")])],-1),d=s("h3",{id:"_9-2-gauss-の法則",tabindex:"-1"},[a("9.2: Gauss の法則 "),s("a",{class:"header-anchor",href:"#_9-2-gauss-の法則","aria-label":'Permalink to "9.2: Gauss の法則"'},"​")],-1),u=s("ol",{start:"2"},[s("li",null,[s("p",null,[a("Gauss の法則 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"S"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\oint \\boldsymbol{B} \\cdot \\mathrm{d} \\boldsymbol{S}=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1111em","vertical-align":"-0.3061em"}}),s("span",{class:"mop op-symbol small-op",style:{"margin-right":"0.19445em",position:"relative",top:"-0.0006em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(",")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∮"),s("mi",null,"ε"),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"S"),s("mo",null,"="),s("mi",null,"Q"),s("mo",{separator:"true"},","),s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"g"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"S"),s("mo",null,"="),s("mo",null,"−"),s("mn",null,"4"),s("mi",null,"π"),s("mi",null,"G"),s("mi",null,"M")]),s("annotation",{encoding:"application/x-tex"},"\\oint \\varepsilon \\boldsymbol{E} \\cdot \\mathrm{d} \\boldsymbol{S}=Q, \\oint \\boldsymbol{g} \\cdot \\mathrm{d} \\boldsymbol{S}=-4 \\pi G M ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mord mathnormal"},"Q"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"g")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM")])])])])])])],-1),y=s("h3",{id:"_9-3-循環定理",tabindex:"-1"},[a("9.3: 循環定理 "),s("a",{class:"header-anchor",href:"#_9-3-循環定理","aria-label":'Permalink to "9.3: 循環定理"'},"​")],-1),b=s("ol",{start:"3"},[s("li",null,[s("p",null,"循環定理 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l"),s("mo",null,"="),s("mn",null,"0"),s("mo",{stretchy:"false"},"("),s("mo",null,"="),s("mover",{accent:"true"},[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"˙")]),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mo",null,"∮"),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l")]),s("mi",null,"μ")]),s("mo",null,"="),s("mi",null,"I"),s("mo",{separator:"true"},","),s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"g"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\oint \\boldsymbol{E} \\cdot \\mathrm{d} \\boldsymbol{l}=0(=\\dot{\\Phi}), \\oint \\frac{\\boldsymbol{B} \\cdot \\mathrm{d} \\boldsymbol{l}}{\\mu}=I, \\oint \\boldsymbol{g} \\cdot \\mathrm{d} \\boldsymbol{l}=0 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mopen"},"("),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2519em","vertical-align":"-0.8804em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9202em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},"Φ")]),s("span",{style:{top:"-3.2523em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1389em"}},[s("span",{class:"mord"},"˙")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"μ")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8804em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"g")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])])])])])],-1),v=s("h3",{id:"_9-4-電流素片により生じる磁束密度",tabindex:"-1"},[a("9.4: 電流素片により生じる磁束密度 "),s("a",{class:"header-anchor",href:"#_9-4-電流素片により生じる磁束密度","aria-label":'Permalink to "9.4: 電流素片により生じる磁束密度"'},"​")],-1),x=s("ol",{start:"4"},[s("li",null,[a("電流素片により生じる磁束密度 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"μ"),s("mi",null,"I")]),s("mrow",null,[s("mn",null,"4"),s("mi",null,"π")])]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l"),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"r")])]),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")])]),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{d} \\boldsymbol{B}=\\frac{\\mu I}{4 \\pi} \\frac{\\mathrm{d} \\boldsymbol{l} \\times \\boldsymbol{e}_r}{r^2} . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0574em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3603em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},".")])])])])]),a(" したがって電流 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),a(" が流れる円形回路の中心では "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"μ"),s("mn",null,"0")]),s("mi",null,"I")]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"r")])])]),s("annotation",{encoding:"application/x-tex"},"B=\\frac{\\mu_0 I}{2 r}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2694em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9244em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(".")])],-1),w=s("h3",{id:"_9-5-ローレンツ力",tabindex:"-1"},[a("9.5: ローレンツ力 "),s("a",{class:"header-anchor",href:"#_9-5-ローレンツ力","aria-label":'Permalink to "9.5: ローレンツ力"'},"​")],-1),k=s("ol",{start:"5"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",null,"e"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"+"),s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"I"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"B"),s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}=e(\\boldsymbol{E}+\\boldsymbol{v} \\times \\boldsymbol{B}), \\boldsymbol{F}=\\boldsymbol{I} \\times \\boldsymbol{B} l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"e"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7694em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.07778em"}},"I")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(".")])],-1),_=s("h3",{id:"_9-6-gauss-の定理と循環定理より",tabindex:"-1"},[a("9.6: Gauss の定理と循環定理より "),s("a",{class:"header-anchor",href:"#_9-6-gauss-の定理と循環定理より","aria-label":'Permalink to "9.6: Gauss の定理と循環定理より"'},"​")],-1),z=s("ol",{start:"6"},[s("li",null,[a("Gauss の定理と循環定理より:帯電した導線について "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"σ"),s("mrow",null,[s("mn",null,"2"),s("mi",null,"π"),s("msub",null,[s("mi",null,"ε"),s("mn",null,"0")]),s("mi",null,"r")])])]),s("annotation",{encoding:"application/x-tex"},"E=\\frac{\\sigma}{2 \\pi \\varepsilon_0 r}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1405em","vertical-align":"-0.4451em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"ε"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4451em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(", 電流が流れる導線について "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"μ"),s("mn",null,"0")]),s("mi",null,"I")]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"π"),s("mi",null,"r")])])]),s("annotation",{encoding:"application/x-tex"},"B=\\frac{\\mu_0 I}{2 \\pi r}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2694em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9244em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 帯電した面について "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"σ"),s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mi",null,"ε"),s("mn",null,"0")])])])]),s("annotation",{encoding:"application/x-tex"},"E=\\frac{\\sigma}{2 \\varepsilon_0}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1405em","vertical-align":"-0.4451em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"ε"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4451em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(", 電流が流れる面につい て "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"μ"),s("mn",null,"0")]),s("mi",null,"i")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"B=\\frac{\\mu_0 i}{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2528em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9078em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight"},"i")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 一様に帯電した球殼(又は無限に長い円 筒)の内部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"E=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(", 軸に沿って表面に電流が流れる 円筒の内部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"B=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 密度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ρ")]),s("annotation",{encoding:"application/x-tex"},"\\rho")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ")])])]),a(" で一様に帯電, 又は一様 な電流 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"i")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{i}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6933em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"i")])])])])]),a(" が流れる, 球 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"d"),s("mo",null,"="),s("mn",null,"3"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/")]),s("annotation",{encoding:"application/x-tex"},"(d=3) /")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/")])])]),a(" 円柱 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"d"),s("mo",null,"−"),s("mn",null,"2"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/")]),s("annotation",{encoding:"application/x-tex"},"(d-2) /")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/")])])]),a(" 平面 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"d"),s("mo",null,"="),s("mn",null,"1"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(d=1)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")")])])]),a(" の内部で,"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"ρ"),s("mrow",null,[s("mi",null,"ε"),s("mi",null,"d")])]),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mrow",null,[s("mi",null,"μ"),s("mi",null,"d")])]),s("mi",{mathvariant:"bold-italic"},"i"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"r")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{E}=\\frac{\\rho}{\\varepsilon d} \\boldsymbol{r}, \\boldsymbol{B}=\\frac{1}{\\mu d} \\boldsymbol{i} \\times \\boldsymbol{r} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.7936em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1076em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mord mathnormal"},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2019em","vertical-align":"-0.8804em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord mathnormal"},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8804em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"i")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])])])])])])])])],-1),f=s("h3",{id:"_9-7-長いソレノイド",tabindex:"-1"},[a("9.7: 長いソレノイド "),s("a",{class:"header-anchor",href:"#_9-7-長いソレノイド","aria-label":'Permalink to "9.7: 長いソレノイド"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("長いソレノイド: 内部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mi",null,"μ"),s("mi",null,"n"),s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"B=\\mu n I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),a(", 外部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"B=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 磁束 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"="),s("mi",null,"N"),s("mi",null,"B"),s("mi",null,"S"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"n"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"N"),s("mi",null,"l")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"\\Phi=N B S\\left(n=\\frac{N}{l}\\right)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2223em","vertical-align":"-0.35em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"NBS"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.01968em"}},"l")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"N")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])])])])]),a(". インダクタンス "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"L"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"L=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"I"),s("mo",null,"="),s("mi",null,"μ"),s("msup",null,[s("mi",null,"n"),s("mn",null,"2")]),s("mi",null,"V")]),s("annotation",{encoding:"application/x-tex"},"\\Phi / I=\\mu n^2 V")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V")])])]),a(". 短いソレノイド "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msub",null,[s("mi",null,"B"),s("mi",{mathvariant:"normal"},"∥")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"μ"),s("mi",null,"n"),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"Ω")]),s("mrow",null,[s("mn",null,"4"),s("mi",null,"π")])]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"Ω")]),s("annotation",{encoding:"application/x-tex"},": B_{\\|}=\\frac{\\mu n I \\Omega}{4 \\pi}(\\Omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0385em","vertical-align":"-0.3552em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.5198em","margin-left":"-0.0502em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"∥")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3552em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2694em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9244em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"π")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"mord mathnormal mtight"},"n"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord mtight"},"Ω")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"Ω")])])]),a(" は 立体角).")])],-1),B=s("h3",{id:"_9-8-磁場を小型コイルや衝撃検流計で測定する",tabindex:"-1"},[a("9.8: 磁場を小型コイルや衝撃検流計で測定する "),s("a",{class:"header-anchor",href:"#_9-8-磁場を小型コイルや衝撃検流計で測定する","aria-label":'Permalink to "9.8: 磁場を小型コイルや衝撃検流計で測定する"'},"​")],-1),L=s("ol",{start:"9"},[s("li",null,[a("磁場を小型コイルや衝撃検流計で測定する: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"q"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"q=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∫"),s("mfrac",null,[s("mi",null,"V"),s("mi",null,"R")]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"t"),s("mo",null,"="),s("mi",null,"N"),s("mi",null,"S"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"B"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"\\int \\frac{V}{R} \\mathrm{~d} t=N S \\Delta B / R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2173em","vertical-align":"-0.345em"}}),s("span",{class:"mop op-symbol small-op",style:{"margin-right":"0.19445em",position:"relative",top:"-0.0006em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.22222em"}},"V")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"NS"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),a(".")])],-1),q=s("h3",{id:"_9-9-静電場のエネルギー",tabindex:"-1"},[a("9.9: 静電場のエネルギー "),s("a",{class:"header-anchor",href:"#_9-9-静電場のエネルギー","aria-label":'Permalink to "9.9: 静電場のエネルギー"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("静電場のエネルギー:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mi",null,"k"),s("munder",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"<"),s("mi",null,"j")])]),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"q"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"q"),s("mi",null,"j")])]),s("msub",null,[s("mi",null,"r"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])])]),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mo",null,"∫"),s("mi",null,"ϕ"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"q"),s("mo",{separator:"true"},","),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"q"),s("mo",null,"="),s("mi",null,"ρ"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"V")]),s("annotation",{encoding:"application/x-tex"},"U=k \\sum_{i9.10: 一様に帯電した球面や円筒面の各部分の間に働く力
    1. 一様に帯電した球面や円筒面の各部分の間に働く力 : 帯電による力を静水圧による力に置き換える.

    9.11: 全ての電荷

    ',3),S=s("ol",{start:"12"},[s("li",null,[a("全ての電荷が距離 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" にある場合(例えば,不均一に帯 電した球やリングの中心) "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ϕ"),s("mi",null,"ϕ"),s("mo",null,"="),s("mi",null,"k"),s("mi",null,"Q"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"\\phi \\phi=k Q / r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ϕϕ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord mathnormal"},"Q"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])])])],-1),E=l('

    9.12: 外部電荷

    1. 外部電荷によって引き起こされる正味の電荷(又は電 位)を求めるには, 電荷を「出現」させて問題を対称的 にし,重ね合わせの原理を用いる.

    9.14: 導体

    ',3),F=s("ol",{start:"14"},[s("li",null,[a("導体は電荷や電場を遮蔽する.例えば,中空の球体の 内部の電荷分布は外から見えない(あたかも "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"Q")]),s("annotation",{encoding:"application/x-tex"},"Q")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"Q")])])]),a(" という 電荷を持った導電性の球があるように見える).")])],-1),T=s("h3",{id:"_9-15-静電容量",tabindex:"-1"},[a("9.15: 静電容量 "),s("a",{class:"header-anchor",href:"#_9-15-静電容量","aria-label":'Permalink to "9.15: 静電容量"'},"​")],-1),V=s("ol",{start:"15"},[s("li",null,[a("静電容量: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"C"),s("mo",null,"="),s("mi",null,"ε"),s("mi",null,"S"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"C=\\varepsilon S / d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07153em"}},"C"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"εS"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"d")])])]),a(" (平板), "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"4"),s("mi",null,"π"),s("mi",null,"ε"),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"4 \\pi \\varepsilon r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" (球), "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2"),s("mi",null,"π"),s("mi",null,"ε"),s("mi",null,"l"),s("mo",{stretchy:"false"},"("),s("mi",null,"ln"),s("mo",null,"⁡"),s("mi",null,"R"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"1")])])]),s("annotation",{encoding:"application/x-tex"},"2 \\pi \\varepsilon l(\\ln R / r)^{-1}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"εl"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},"ln"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"1")])])])])])])])])])])]),a(" (同軸円筒).")])],-1),N=s("h3",{id:"_9-16-双極子モーメント",tabindex:"-1"},[a("9.16: 双極子モーメント "),s("a",{class:"header-anchor",href:"#_9-16-双極子モーメント","aria-label":'Permalink to "9.16: 双極子モーメント"'},"​")],-1),j=s("ol",{start:"16"},[s("li",null,[s("p",null,"双極子モーメント:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mi",null,"e")]),s("mo",null,"="),s("mo",null,"∑"),s("msub",null,[s("mi",null,"q"),s("mi",null,"i")]),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"r"),s("mi",null,"i")]),s("mo",null,"="),s("mi",null,"q"),s("mi",{mathvariant:"bold-italic"},"d"),s("mo",{separator:"true"},","),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mi",null,"μ")]),s("mo",null,"="),s("mi",null,"I"),s("mi",{mathvariant:"bold-italic"},"S")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{p}_e=\\sum q_i \\boldsymbol{r}_i=q \\boldsymbol{d}, \\boldsymbol{p}_\\mu=I \\boldsymbol{S} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6886em","vertical-align":"-0.2441em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.0573em"}},[s("span",{style:{top:"-2.4559em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"e")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2441em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.6em","vertical-align":"-0.55em"}}),s("span",{class:"mop op-symbol large-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0747em","vertical-align":"-0.3802em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"d")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.0573em"}},[s("span",{style:{top:"-2.4559em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"μ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3802em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])])])])])])])])],-1),R=s("h3",{id:"_9-17-双極子場",tabindex:"-1"},[a("9.17: 双極子場 "),s("a",{class:"header-anchor",href:"#_9-17-双極子場","aria-label":'Permalink to "9.17: 双極子場"'},"​")],-1),C=s("ol",{start:"17"},[s("li",null,[a("双極子場 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ϕ"),s("mo",null,"="),s("mi",null,"k"),s("mi",{mathvariant:"bold-italic"},"p"),s("mo",null,"⋅"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"r")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"E"),s("mo",{separator:"true"},","),s("mi",null,"B"),s("mo",null,"∝"),s("msup",null,[s("mi",null,"r"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"3")])])]),s("annotation",{encoding:"application/x-tex"},"\\phi=k \\boldsymbol{p} \\cdot \\boldsymbol{e}_r / r^2, E, B \\propto r^{-3}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ϕ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"3")])])])])])])])])])])])])],-1),Q=s("h3",{id:"_9-18-双極子に働く力",tabindex:"-1"},[a("9.18: 双極子に働く力 "),s("a",{class:"header-anchor",href:"#_9-18-双極子に働く力","aria-label":'Permalink to "9.18: 双極子に働く力"'},"​")],-1),A=s("ol",{start:"19"},[s("li",null,[a("双極子に働く力 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mi",null,"e")]),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",{fence:"true"},")")]),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")]),s("mo",{separator:"true"},","),s("mi",null,"F"),s("mo",null,"="),s("msup",null,[s("mrow",null,[s("mo",{fence:"true"},"("),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"p"),s("mi",null,"μ")]),s("mo",null,"⋅"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",{fence:"true"},")")]),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),s("annotation",{encoding:"application/x-tex"},"F=\\left(\\boldsymbol{p}_e \\cdot \\boldsymbol{E}\\right)^{\\prime}, F=\\left(\\boldsymbol{p}_\\mu \\cdot \\boldsymbol{B}\\right)^{\\prime}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1418em","vertical-align":"-0.25em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.0573em"}},[s("span",{style:{top:"-2.4559em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"e")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2441em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},")")]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8918em"}},[s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.372em","vertical-align":"-0.3802em"}}),s("span",{class:"minner"},[s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"p")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.0573em"}},[s("span",{style:{top:"-2.4559em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"μ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3802em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9918em"}},[s("span",{style:{top:"-3.3029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])])])])]),a(" [訳 者注 : ここの微分はむしろ "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"grad"),s("mo",null,"⁡")]),s("annotation",{encoding:"application/x-tex"},"\\operatorname{grad}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mop"},[s("span",{class:"mord mathrm"},"grad")])])])]),a(" である]. 2 つの双極 子間の相互作用 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("mi",null,"F"),s("mo",null,"∝"),s("msup",null,[s("mi",null,"r"),s("mrow",null,[s("mo",null,"−"),s("mn",null,"4")])])]),s("annotation",{encoding:"application/x-tex"},": F \\propto r^{-4}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"−"),s("span",{class:"mord mtight"},"4")])])])])])])])])])])]),a(".")])],-1),G=s("h3",{id:"_9-19-磁気双極子としての点電荷",tabindex:"-1"},[a("9.19: 磁気双極子としての点電荷 "),s("a",{class:"header-anchor",href:"#_9-19-磁気双極子としての点電荷","aria-label":'Permalink to "9.19: 磁気双極子としての点電荷"'},"​")],-1),U=s("ol",{start:"19"},[s("li",null,[a("磁気双極子としての点電荷 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"p"),s("mi",null,"μ")]),s("mo",null,"∝"),s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"∝"),s("msubsup",null,[s("mi",null,"v"),s("mo",{lspace:"0em",rspace:"0em"},"⊥"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"B")]),s("annotation",{encoding:"application/x-tex"},"p_\\mu \\propto \\Phi \\propto v_{\\perp}^2 / B")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7167em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"p"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"μ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0972em","vertical-align":"-0.2831em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-2.4169em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mrel mtight"},"⊥")])])]),s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2831em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B")])])]),a(" は断熱 不変量 ("),s("a",{href:"./4#_4-22-断熱不変量"},"Section 4: #22"),a(" 参照).")])],-1),O=l('

    9.20: 鏡像法

    1. 鏡像法 : 接地された(磁石の場合は超電導の)平面が鏡 の役割をする. 接地された(又は孤立した)球体の場 は, 球体の内部にある 1 つ(又は 2 つ)の架空の電荷 のつくる場として求められる. 平面導波管(金属板の 間のスリット)内の場は, 電磁平面波の重ね合わせと して求められる.

    9.21: 一様(電)場中の球 (円柱) の分極

    ',3),D=s("ol",{start:"21"},[s("li",null,[a("一様(電)場中の球 (円柱) の分極 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mo",null,"+"),s("mi",null,"ρ")]),s("annotation",{encoding:"application/x-tex"},"(+\\rho")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"+"),s("span",{class:"mord mathnormal"},"ρ")])])]),a(" と "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"−"),s("mi",null,"ρ")]),s("annotation",{encoding:"application/x-tex"},"-\\rho")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord mathnormal"},"ρ")])])]),a(" に一 様に帯電した球 (円柱) の重ね合わせで, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d"),s("mo",null,"∝"),s("mi",null,"E")]),s("annotation",{encoding:"application/x-tex"},"d \\propto E")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"∝"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E")])])]),a(".")])],-1),$=s("h3",{id:"_9-22-渦電流",tabindex:"-1"},[a("9.22: 渦電流 "),s("a",{class:"header-anchor",href:"#_9-22-渦電流","aria-label":'Permalink to "9.22: 渦電流"'},"​")],-1),H=s("ol",{start:"22"},[s("li",null,[a("渦電流: 電流損失密度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"≈"),s("msup",null,[s("mi",null,"B"),s("mn",null,"2")]),s("msup",null,[s("mi",null,"v"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"ρ"),s("mi",{mathvariant:"normal"},"."),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"\\approx B^2 v^2 / \\rho .1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4831em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"v"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"ρ"),s("span",{class:"mord"},".1")])])]),a(" 回の通過で与え られる運動量 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mi",null,"τ"),s("mo",null,"≈"),s("msup",null,[s("mi",null,"B"),s("mn",null,"2")]),s("msup",null,[s("mi",null,"a"),s("mn",null,"3")]),s("mi",null,"d"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"ρ")]),s("annotation",{encoding:"application/x-tex"},"F \\tau \\approx B^2 a^3 d / \\rho")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.1132em"}},"τ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≈"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])])])])])]),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal"},"ρ")])])]),a(" (ここで "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"d")]),s("annotation",{encoding:"application/x-tex"},"d")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathnormal"},"d")])])]),a(" は厚さ, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"a")]),s("annotation",{encoding:"application/x-tex"},"a")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"a")])])]),a(" は大きさ).")])],-1);function J(K,W,X,Y,Z,ss){const t=n;return e(),i("div",null,[c,r(t,{readTime:"4",words:"950"}),h,o,g,d,u,y,b,v,x,w,k,_,z,f,M,B,L,q,I,P,S,E,F,T,V,N,j,R,C,Q,A,G,U,O,D,$,H])}const ms=m(p,[["render",J]]);export{ns as __pageData,ms as default}; diff --git a/assets/academic_physics_ipho-formulas-jpn_9.md.da4d857a.lean.js b/assets/academic_physics_ipho-formulas-jpn_9.md.083302ab.lean.js similarity index 99% rename from assets/academic_physics_ipho-formulas-jpn_9.md.da4d857a.lean.js rename to assets/academic_physics_ipho-formulas-jpn_9.md.083302ab.lean.js index a308dcb8..010cee8f 100644 --- a/assets/academic_physics_ipho-formulas-jpn_9.md.da4d857a.lean.js +++ b/assets/academic_physics_ipho-formulas-jpn_9.md.083302ab.lean.js @@ -1 +1 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as m,o as e,c as i,H as r,k as s,a,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const ns=JSON.parse('{"title":"Formulas for IPhO 日本語版: Section 9","description":"","frontmatter":{},"headers":[],"relativePath":"academic/physics/ipho-formulas-jpn/9.md","filePath":"academic/physics/ipho-formulas-jpn/9.md","lastUpdated":1695377563000}'),p={name:"academic/physics/ipho-formulas-jpn/9.md"},c=s("h1",{id:"formulas-for-ipho-日本語版-section-9",tabindex:"-1"},[a("Formulas for IPhO 日本語版: Section 9 "),s("a",{class:"header-anchor",href:"#formulas-for-ipho-日本語版-section-9","aria-label":'Permalink to "Formulas for IPhO 日本語版: Section 9"'},"​")],-1),h=s("h2",{id:"_9-電磁気学",tabindex:"-1"},[a("9: 電磁気学 "),s("a",{class:"header-anchor",href:"#_9-電磁気学","aria-label":'Permalink to "9: 電磁気学"'},"​")],-1),o=s("h3",{id:"_9-1-coulomb-の法則",tabindex:"-1"},[a("9.1: Coulomb の法則 "),s("a",{class:"header-anchor",href:"#_9-1-coulomb-の法則","aria-label":'Permalink to "9.1: Coulomb の法則"'},"​")],-1),g=s("ol",null,[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("mi",null,"k"),s("msub",null,[s("mi",null,"q"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"q"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("mi",null,"U"),s("mo",null,"="),s("mi",null,"k"),s("msub",null,[s("mi",null,"q"),s("mn",null,"1")]),s("msub",null,[s("mi",null,"q"),s("mn",null,"2")]),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"r")]),s("annotation",{encoding:"application/x-tex"},"F=k q_1 q_2 / r^2, U=k q_1 q_2 / r")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"U"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03148em"}},"k"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r")])])]),a(" で, Kepler の法則が 使える ("),s("a",{href:"./12"},"Section 12 参照"),a(").")])],-1),d=s("h3",{id:"_9-2-gauss-の法則",tabindex:"-1"},[a("9.2: Gauss の法則 "),s("a",{class:"header-anchor",href:"#_9-2-gauss-の法則","aria-label":'Permalink to "9.2: Gauss の法則"'},"​")],-1),u=s("ol",{start:"2"},[s("li",null,[s("p",null,[a("Gauss の法則 : "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"S"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\oint \\boldsymbol{B} \\cdot \\mathrm{d} \\boldsymbol{S}=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1111em","vertical-align":"-0.3061em"}}),s("span",{class:"mop op-symbol small-op",style:{"margin-right":"0.19445em",position:"relative",top:"-0.0006em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(",")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∮"),s("mi",null,"ε"),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"S"),s("mo",null,"="),s("mi",null,"Q"),s("mo",{separator:"true"},","),s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"g"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"S"),s("mo",null,"="),s("mo",null,"−"),s("mn",null,"4"),s("mi",null,"π"),s("mi",null,"G"),s("mi",null,"M")]),s("annotation",{encoding:"application/x-tex"},"\\oint \\varepsilon \\boldsymbol{E} \\cdot \\mathrm{d} \\boldsymbol{S}=Q, \\oint \\boldsymbol{g} \\cdot \\mathrm{d} \\boldsymbol{S}=-4 \\pi G M ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mord mathnormal"},"Q"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"g")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05382em"}},"S")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"−"),s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.10903em"}},"GM")])])])])])])],-1),y=s("h3",{id:"_9-3-循環定理",tabindex:"-1"},[a("9.3: 循環定理 "),s("a",{class:"header-anchor",href:"#_9-3-循環定理","aria-label":'Permalink to "9.3: 循環定理"'},"​")],-1),b=s("ol",{start:"3"},[s("li",null,[s("p",null,"循環定理 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l"),s("mo",null,"="),s("mn",null,"0"),s("mo",{stretchy:"false"},"("),s("mo",null,"="),s("mover",{accent:"true"},[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"˙")]),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mo",null,"∮"),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l")]),s("mi",null,"μ")]),s("mo",null,"="),s("mi",null,"I"),s("mo",{separator:"true"},","),s("mo",null,"∮"),s("mi",{mathvariant:"bold-italic"},"g"),s("mo",null,"⋅"),s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"\\oint \\boldsymbol{E} \\cdot \\mathrm{d} \\boldsymbol{l}=0(=\\dot{\\Phi}), \\oint \\frac{\\boldsymbol{B} \\cdot \\mathrm{d} \\boldsymbol{l}}{\\mu}=I, \\oint \\boldsymbol{g} \\cdot \\mathrm{d} \\boldsymbol{l}=0 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"0"),s("span",{class:"mopen"},"("),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2519em","vertical-align":"-0.8804em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9202em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},"Φ")]),s("span",{style:{top:"-3.2523em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.1389em"}},[s("span",{class:"mord"},"˙")])])])])])]),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"μ")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8804em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2222em","vertical-align":"-0.8622em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop op-symbol large-op",style:{"margin-right":"0.44445em",position:"relative",top:"-0.0011em"}},"∮"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"g")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"⋅"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])])])])])],-1),v=s("h3",{id:"_9-4-電流素片により生じる磁束密度",tabindex:"-1"},[a("9.4: 電流素片により生じる磁束密度 "),s("a",{class:"header-anchor",href:"#_9-4-電流素片により生じる磁束密度","aria-label":'Permalink to "9.4: 電流素片により生じる磁束密度"'},"​")],-1),x=s("ol",{start:"4"},[s("li",null,[a("電流素片により生じる磁束密度 :"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"μ"),s("mi",null,"I")]),s("mrow",null,[s("mn",null,"4"),s("mi",null,"π")])]),s("mfrac",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"d"),s("mi",{mathvariant:"bold-italic"},"l"),s("mo",null,"×"),s("msub",null,[s("mi",{mathvariant:"bold-italic"},"e"),s("mi",null,"r")])]),s("msup",null,[s("mi",null,"r"),s("mn",null,"2")])]),s("mi",{mathvariant:"normal"},".")]),s("annotation",{encoding:"application/x-tex"},"\\mathrm{d} \\boldsymbol{B}=\\frac{\\mu I}{4 \\pi} \\frac{\\mathrm{d} \\boldsymbol{l} \\times \\boldsymbol{e}_r}{r^2} . ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.0574em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3603em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"4"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7401em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathrm"},"d"),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.0088em"}},"l")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"e")])]),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1514em"}},[s("span",{style:{top:"-2.55em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},".")])])])])]),a(" したがって電流 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),a(" が流れる円形回路の中心では "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"μ"),s("mn",null,"0")]),s("mi",null,"I")]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"r")])])]),s("annotation",{encoding:"application/x-tex"},"B=\\frac{\\mu_0 I}{2 r}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2694em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9244em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(".")])],-1),w=s("h3",{id:"_9-5-ローレンツ力",tabindex:"-1"},[a("9.5: ローレンツ力 "),s("a",{class:"header-anchor",href:"#_9-5-ローレンツ力","aria-label":'Permalink to "9.5: ローレンツ力"'},"​")],-1),k=s("ol",{start:"5"},[s("li",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",null,"e"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"+"),s("mi",{mathvariant:"bold-italic"},"v"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",{stretchy:"false"},")"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"F"),s("mo",null,"="),s("mi",{mathvariant:"bold-italic"},"I"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"B"),s("mi",null,"l")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{F}=e(\\boldsymbol{E}+\\boldsymbol{v} \\times \\boldsymbol{B}), \\boldsymbol{F}=\\boldsymbol{I} \\times \\boldsymbol{B} l")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"e"),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03704em"}},"v")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mclose"},")"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.15972em"}},"F")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7694em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.07778em"}},"I")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l")])])]),a(".")])],-1),_=s("h3",{id:"_9-6-gauss-の定理と循環定理より",tabindex:"-1"},[a("9.6: Gauss の定理と循環定理より "),s("a",{class:"header-anchor",href:"#_9-6-gauss-の定理と循環定理より","aria-label":'Permalink to "9.6: Gauss の定理と循環定理より"'},"​")],-1),z=s("ol",{start:"6"},[s("li",null,[a("Gauss の定理と循環定理より:帯電した導線について "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"σ"),s("mrow",null,[s("mn",null,"2"),s("mi",null,"π"),s("msub",null,[s("mi",null,"ε"),s("mn",null,"0")]),s("mi",null,"r")])])]),s("annotation",{encoding:"application/x-tex"},"E=\\frac{\\sigma}{2 \\pi \\varepsilon_0 r}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1405em","vertical-align":"-0.4451em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"ε"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4451em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(", 電流が流れる導線について "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"μ"),s("mn",null,"0")]),s("mi",null,"I")]),s("mrow",null,[s("mn",null,"2"),s("mi",null,"π"),s("mi",null,"r")])])]),s("annotation",{encoding:"application/x-tex"},"B=\\frac{\\mu_0 I}{2 \\pi r}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2694em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9244em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"π"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 帯電した面について "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"σ"),s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mi",null,"ε"),s("mn",null,"0")])])])]),s("annotation",{encoding:"application/x-tex"},"E=\\frac{\\sigma}{2 \\varepsilon_0}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1405em","vertical-align":"-0.4451em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6954em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2"),s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"ε"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"σ")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4451em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(", 電流が流れる面につい て "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"μ"),s("mn",null,"0")]),s("mi",null,"i")]),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"B=\\frac{\\mu_0 i}{2}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2528em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9078em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3173em"}},[s("span",{style:{top:"-2.357em","margin-left":"0em","margin-right":"0.0714em"}},[s("span",{class:"pstrut",style:{height:"2.5em"}}),s("span",{class:"sizing reset-size3 size1 mtight"},[s("span",{class:"mord mtight"},"0")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.143em"}},[s("span")])])])])]),s("span",{class:"mord mathnormal mtight"},"i")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})])])])]),a(". 一様に帯電した球殼(又は無限に長い円 筒)の内部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"E=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(", 軸に沿って表面に電流が流れる 円筒の内部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"B=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 密度 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"ρ")]),s("annotation",{encoding:"application/x-tex"},"\\rho")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"ρ")])])]),a(" で一様に帯電, 又は一様 な電流 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"i")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{i}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6933em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"i")])])])])]),a(" が流れる, 球 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"d"),s("mo",null,"="),s("mn",null,"3"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/")]),s("annotation",{encoding:"application/x-tex"},"(d=3) /")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/")])])]),a(" 円柱 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"d"),s("mo",null,"−"),s("mn",null,"2"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"/")]),s("annotation",{encoding:"application/x-tex"},"(d-2) /")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mclose"},")"),s("span",{class:"mord"},"/")])])]),a(" 平面 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"d"),s("mo",null,"="),s("mn",null,"1"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(d=1)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"d"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")")])])]),a(" の内部で,"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"bold-italic"},"E"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"ρ"),s("mrow",null,[s("mi",null,"ε"),s("mi",null,"d")])]),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"bold-italic"},"B"),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mrow",null,[s("mi",null,"μ"),s("mi",null,"d")])]),s("mi",{mathvariant:"bold-italic"},"i"),s("mo",null,"×"),s("mi",{mathvariant:"bold-italic"},"r")]),s("annotation",{encoding:"application/x-tex"},"\\boldsymbol{E}=\\frac{\\rho}{\\varepsilon d} \\boldsymbol{r}, \\boldsymbol{B}=\\frac{1}{\\mu d} \\boldsymbol{i} \\times \\boldsymbol{r} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6861em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.05451em"}},"E")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.7936em","vertical-align":"-0.686em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.1076em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ε"),s("span",{class:"mord mathnormal"},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"ρ")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.04835em"}},"B")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.2019em","vertical-align":"-0.8804em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3214em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord mathnormal"},"d")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8804em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol"},"i")])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4444em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord boldsymbol",style:{"margin-right":"0.03194em"}},"r")])])])])])])])])],-1),f=s("h3",{id:"_9-7-長いソレノイド",tabindex:"-1"},[a("9.7: 長いソレノイド "),s("a",{class:"header-anchor",href:"#_9-7-長いソレノイド","aria-label":'Permalink to "9.7: 長いソレノイド"'},"​")],-1),M=s("ol",{start:"7"},[s("li",null,[a("長いソレノイド: 内部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mi",null,"μ"),s("mi",null,"n"),s("mi",null,"I")]),s("annotation",{encoding:"application/x-tex"},"B=\\mu n I")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I")])])]),a(", 外部で "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"B"),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"B=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(". 磁束 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mo",null,"="),s("mi",null,"N"),s("mi",null,"B"),s("mi",null,"S"),s("mrow",null,[s("mo",{fence:"true"},"("),s("mi",null,"n"),s("mo",null,"="),s("mfrac",null,[s("mi",null,"N"),s("mi",null,"l")]),s("mo",{fence:"true"},")")])]),s("annotation",{encoding:"application/x-tex"},"\\Phi=N B S\\left(n=\\frac{N}{l}\\right)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord"},"Φ"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2223em","vertical-align":"-0.35em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"NBS"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},"(")]),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.01968em"}},"l")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.10903em"}},"N")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size1"},")")])])])])]),a(". インダクタンス "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"L"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"L=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"L"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",{mathvariant:"normal"},"Φ"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"I"),s("mo",null,"="),s("mi",null,"μ"),s("msup",null,[s("mi",null,"n"),s("mn",null,"2")]),s("mi",null,"V")]),s("annotation",{encoding:"application/x-tex"},"\\Phi / I=\\mu n^2 V")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord"},"Φ/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal"},"μ"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"n"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.22222em"}},"V")])])]),a(". 短いソレノイド "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,":"),s("msub",null,[s("mi",null,"B"),s("mi",{mathvariant:"normal"},"∥")]),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mi",null,"μ"),s("mi",null,"n"),s("mi",null,"I"),s("mi",{mathvariant:"normal"},"Ω")]),s("mrow",null,[s("mn",null,"4"),s("mi",null,"π")])]),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"normal"},"Ω")]),s("annotation",{encoding:"application/x-tex"},": B_{\\|}=\\frac{\\mu n I \\Omega}{4 \\pi}(\\Omega")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mrel"},":"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0385em","vertical-align":"-0.3552em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3448em"}},[s("span",{style:{top:"-2.5198em","margin-left":"-0.0502em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"∥")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3552em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2694em","vertical-align":"-0.345em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.9244em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"4"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"π")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.4461em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"μ"),s("span",{class:"mord mathnormal mtight"},"n"),s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I"),s("span",{class:"mord mtight"},"Ω")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"Ω")])])]),a(" は 立体角).")])],-1),B=s("h3",{id:"_9-8-磁場を小型コイルや衝撃検流計で測定する",tabindex:"-1"},[a("9.8: 磁場を小型コイルや衝撃検流計で測定する "),s("a",{class:"header-anchor",href:"#_9-8-磁場を小型コイルや衝撃検流計で測定する","aria-label":'Permalink to "9.8: 磁場を小型コイルや衝撃検流計で測定する"'},"​")],-1),L=s("ol",{start:"9"},[s("li",null,[a("磁場を小型コイルや衝撃検流計で測定する: "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"q"),s("mo",null,"=")]),s("annotation",{encoding:"application/x-tex"},"q=")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"q"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"=")])])]),a(),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",null,"∫"),s("mfrac",null,[s("mi",null,"V"),s("mi",null,"R")]),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"t"),s("mo",null,"="),s("mi",null,"N"),s("mi",null,"S"),s("mi",{mathvariant:"normal"},"Δ"),s("mi",null,"B"),s("mi",{mathvariant:"normal"},"/"),s("mi",null,"R")]),s("annotation",{encoding:"application/x-tex"},"\\int \\frac{V}{R} \\mathrm{~d} t=N S \\Delta B / R")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.2173em","vertical-align":"-0.345em"}}),s("span",{class:"mop op-symbol small-op",style:{"margin-right":"0.19445em",position:"relative",top:"-0.0006em"}},"∫"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8723em"}},[s("span",{style:{top:"-2.655em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.00773em"}},"R")])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.394em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.22222em"}},"V")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.345em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mord"},[s("span",{class:"mspace nobreak"}," "),s("span",{class:"mord mathrm"},"d")]),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"NS"),s("span",{class:"mord"},"Δ"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05017em"}},"B"),s("span",{class:"mord"},"/"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.00773em"}},"R")])])]),a(".")])],-1),q=s("h3",{id:"_9-9-静電場のエネルギー",tabindex:"-1"},[a("9.9: 静電場のエネルギー "),s("a",{class:"header-anchor",href:"#_9-9-静電場のエネルギー","aria-label":'Permalink to "9.9: 静電場のエネルギー"'},"​")],-1),I=s("ol",{start:"9"},[s("li",null,[a("静電場のエネルギー:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"U"),s("mo",null,"="),s("mi",null,"k"),s("munder",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"<"),s("mi",null,"j")])]),s("mfrac",null,[s("mrow",null,[s("msub",null,[s("mi",null,"q"),s("mi",null,"i")]),s("msub",null,[s("mi",null,"q"),s("mi",null,"j")])]),s("msub",null,[s("mi",null,"r"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])])]),s("mo",null,"="),s("mfrac",null,[s("mn",null,"1"),s("mn",null,"2")]),s("mo",null,"∫"),s("mi",null,"ϕ"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"q"),s("mo",{separator:"true"},","),s("mrow",null,[s("mtext",null," "),s("mi",{mathvariant:"normal"},"d")]),s("mi",null,"q"),s("mo",null,"="),s("mi",null,"ρ"),s("mo",{stretchy:"false"},"("),s("mi",{mathvariant:"bold-italic"},"r"),s("mo",{stretchy:"false"},")"),s("mi",{mathvariant:"normal"},"d"),s("mi",null,"V")]),s("annotation",{encoding:"application/x-tex"},"U=k \\sum_{i

    This table of vocabularies are from "Sadlier Vocabulary Workshop-Level G (Unit 4)" with their corresponding textbook definitions and part of speeches (from some of them) made into a collection.

    VocabularyDefinition
    Atrophy(n.) the wasting away of a body organ or tissue; any progressive decline or failure; (v.) to waste away
    BastionA fortified place, stronghold
    ConcordA state of agreement, harmony, unanimity; a treaty, pact, covenant
    Consummate(adj.) complete or perfect in the highest degree; (v.) to bring to a state of completion or perfection
    Disarray(n.) disorder, confusion; (v.) to throw into disorder
    ExigencyUrgency, pressure; urgent demand, pressing need; an emergency
    FlotsamFloating debris; homeless, impoverished people
    FreneticFrenzied, highly agitated
    GleanTo gather bit by bit; to gather small quantities of grain left in a field by the reapers.
    Grouse(n.) A type of game bird; a complaint; (v.) to complain, grumble
    IncarcerateTo imprison, confine, jail
    Incumbent(adj.) obligatory, required; (n.) one who holds a specific office at the time spoken of
    JocularHumorous, jesting, jolly, joking
    LudicrousRidiculous, laughable, absurd
    MordantBiting or caustic in thought, manner, or style; sharply or bitterly harsh.
    Nettle(n.) a prickly or stinging plant; (v.) to arouse displeasure, impatience, or anger; to vex or irritate severely
    PecuniaryConsisting of or measured in money; of or related to money
    PusillanimousContemptibly cowardly or mean-spirited
    RecumbentIn a reclining position, lying down, in the posture of one sleeping or resting.
    StratagemA scheme to outwit or deceive an opponent or to gain and end.

    Reference

    ',3);function p(m,h,f,y,b,g){const e=r;return a(),d("div",null,[c,i(e,{readTime:"1",words:"299"}),u])}const w=o(l,[["render",p]]);export{V as __pageData,w as default}; +import{_ as r}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as a,c as d,H as i,k as t,a as n,Q as s}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const V=JSON.parse('{"title":"2023-2-27: Vocabulary","description":"Vocabulary list collected for 2023-2-27","frontmatter":{"title":"2023-2-27: Vocabulary","description":"Vocabulary list collected for 2023-2-27"},"headers":[],"relativePath":"academic/vocabulary/2023/02/2023-02-27.md","filePath":"academic/vocabulary/2023/02/2023-02-27.md","lastUpdated":1699051935000}'),l={name:"academic/vocabulary/2023/02/2023-02-27.md"},c=t("h1",{id:"_2023-2-27-vocabulary",tabindex:"-1"},[n("2023-2-27: Vocabulary "),t("a",{class:"header-anchor",href:"#_2023-2-27-vocabulary","aria-label":'Permalink to "2023-2-27: Vocabulary"'},"​")],-1),u=s('

    This table of vocabularies are from "Sadlier Vocabulary Workshop-Level G (Unit 4)" with their corresponding textbook definitions and part of speeches (from some of them) made into a collection.

    VocabularyDefinition
    Atrophy(n.) the wasting away of a body organ or tissue; any progressive decline or failure; (v.) to waste away
    BastionA fortified place, stronghold
    ConcordA state of agreement, harmony, unanimity; a treaty, pact, covenant
    Consummate(adj.) complete or perfect in the highest degree; (v.) to bring to a state of completion or perfection
    Disarray(n.) disorder, confusion; (v.) to throw into disorder
    ExigencyUrgency, pressure; urgent demand, pressing need; an emergency
    FlotsamFloating debris; homeless, impoverished people
    FreneticFrenzied, highly agitated
    GleanTo gather bit by bit; to gather small quantities of grain left in a field by the reapers.
    Grouse(n.) A type of game bird; a complaint; (v.) to complain, grumble
    IncarcerateTo imprison, confine, jail
    Incumbent(adj.) obligatory, required; (n.) one who holds a specific office at the time spoken of
    JocularHumorous, jesting, jolly, joking
    LudicrousRidiculous, laughable, absurd
    MordantBiting or caustic in thought, manner, or style; sharply or bitterly harsh.
    Nettle(n.) a prickly or stinging plant; (v.) to arouse displeasure, impatience, or anger; to vex or irritate severely
    PecuniaryConsisting of or measured in money; of or related to money
    PusillanimousContemptibly cowardly or mean-spirited
    RecumbentIn a reclining position, lying down, in the posture of one sleeping or resting.
    StratagemA scheme to outwit or deceive an opponent or to gain and end.

    Reference

    ',3);function p(m,h,f,y,b,g){const e=r;return a(),d("div",null,[c,i(e,{readTime:"1",words:"299"}),u])}const w=o(l,[["render",p]]);export{V as __pageData,w as default}; diff --git a/assets/academic_vocabulary_2023_02_2023-02-27.md.06541670.lean.js b/assets/academic_vocabulary_2023_02_2023-02-27.md.3ec19aaf.lean.js similarity index 93% rename from assets/academic_vocabulary_2023_02_2023-02-27.md.06541670.lean.js rename to assets/academic_vocabulary_2023_02_2023-02-27.md.3ec19aaf.lean.js index bc9ca483..7aecef46 100644 --- a/assets/academic_vocabulary_2023_02_2023-02-27.md.06541670.lean.js +++ b/assets/academic_vocabulary_2023_02_2023-02-27.md.3ec19aaf.lean.js @@ -1 +1 @@ -import{_ as r}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as a,c as d,H as i,k as t,a as n,Q as s}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const V=JSON.parse('{"title":"2023-2-27: Vocabulary","description":"Vocabulary list collected for 2023-2-27","frontmatter":{"title":"2023-2-27: Vocabulary","description":"Vocabulary list collected for 2023-2-27"},"headers":[],"relativePath":"academic/vocabulary/2023/02/2023-02-27.md","filePath":"academic/vocabulary/2023/02/2023-02-27.md","lastUpdated":1695377563000}'),l={name:"academic/vocabulary/2023/02/2023-02-27.md"},c=t("h1",{id:"_2023-2-27-vocabulary",tabindex:"-1"},[n("2023-2-27: Vocabulary "),t("a",{class:"header-anchor",href:"#_2023-2-27-vocabulary","aria-label":'Permalink to "2023-2-27: Vocabulary"'},"​")],-1),u=s("",3);function p(m,h,f,y,b,g){const e=r;return a(),d("div",null,[c,i(e,{readTime:"1",words:"299"}),u])}const w=o(l,[["render",p]]);export{V as __pageData,w as default}; +import{_ as r}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as a,c as d,H as i,k as t,a as n,Q as s}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const V=JSON.parse('{"title":"2023-2-27: Vocabulary","description":"Vocabulary list collected for 2023-2-27","frontmatter":{"title":"2023-2-27: Vocabulary","description":"Vocabulary list collected for 2023-2-27"},"headers":[],"relativePath":"academic/vocabulary/2023/02/2023-02-27.md","filePath":"academic/vocabulary/2023/02/2023-02-27.md","lastUpdated":1699051935000}'),l={name:"academic/vocabulary/2023/02/2023-02-27.md"},c=t("h1",{id:"_2023-2-27-vocabulary",tabindex:"-1"},[n("2023-2-27: Vocabulary "),t("a",{class:"header-anchor",href:"#_2023-2-27-vocabulary","aria-label":'Permalink to "2023-2-27: Vocabulary"'},"​")],-1),u=s("",3);function p(m,h,f,y,b,g){const e=r;return a(),d("div",null,[c,i(e,{readTime:"1",words:"299"}),u])}const w=o(l,[["render",p]]);export{V as __pageData,w as default}; diff --git a/assets/academic_vocabulary_index.md.f4afb44a.lean.js b/assets/academic_vocabulary_index.md.37eb0530.js similarity index 92% rename from assets/academic_vocabulary_index.md.f4afb44a.lean.js rename to assets/academic_vocabulary_index.md.37eb0530.js index eef554b6..29b861ed 100644 --- a/assets/academic_vocabulary_index.md.f4afb44a.lean.js +++ b/assets/academic_vocabulary_index.md.37eb0530.js @@ -1 +1 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as c,c as r,H as s,k as e,a as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Welcome to My Vocabulary List!","description":"","frontmatter":{},"headers":[],"relativePath":"academic/vocabulary/index.md","filePath":"academic/vocabulary/index.md","lastUpdated":1695377563000}'),l={name:"academic/vocabulary/index.md"},n=e("h1",{id:"welcome-to-my-vocabulary-list",tabindex:"-1"},[i("Welcome to My Vocabulary List! "),e("a",{class:"header-anchor",href:"#welcome-to-my-vocabulary-list","aria-label":'Permalink to "Welcome to My Vocabulary List!"'},"​")],-1);function d(m,_,p,u,y,f){const a=o;return c(),r("div",null,[n,s(a,{readTime:"1",words:"5"})])}const V=t(l,[["render",d]]);export{v as __pageData,V as default}; +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as c,c as r,H as s,k as e,a as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Welcome to My Vocabulary List!","description":"","frontmatter":{},"headers":[],"relativePath":"academic/vocabulary/index.md","filePath":"academic/vocabulary/index.md","lastUpdated":1699051935000}'),l={name:"academic/vocabulary/index.md"},n=e("h1",{id:"welcome-to-my-vocabulary-list",tabindex:"-1"},[i("Welcome to My Vocabulary List! "),e("a",{class:"header-anchor",href:"#welcome-to-my-vocabulary-list","aria-label":'Permalink to "Welcome to My Vocabulary List!"'},"​")],-1);function d(m,_,p,u,y,f){const a=o;return c(),r("div",null,[n,s(a,{readTime:"1",words:"5"})])}const V=t(l,[["render",d]]);export{v as __pageData,V as default}; diff --git a/assets/academic_vocabulary_index.md.f4afb44a.js b/assets/academic_vocabulary_index.md.37eb0530.lean.js similarity index 92% rename from assets/academic_vocabulary_index.md.f4afb44a.js rename to assets/academic_vocabulary_index.md.37eb0530.lean.js index eef554b6..29b861ed 100644 --- a/assets/academic_vocabulary_index.md.f4afb44a.js +++ b/assets/academic_vocabulary_index.md.37eb0530.lean.js @@ -1 +1 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as c,c as r,H as s,k as e,a as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Welcome to My Vocabulary List!","description":"","frontmatter":{},"headers":[],"relativePath":"academic/vocabulary/index.md","filePath":"academic/vocabulary/index.md","lastUpdated":1695377563000}'),l={name:"academic/vocabulary/index.md"},n=e("h1",{id:"welcome-to-my-vocabulary-list",tabindex:"-1"},[i("Welcome to My Vocabulary List! "),e("a",{class:"header-anchor",href:"#welcome-to-my-vocabulary-list","aria-label":'Permalink to "Welcome to My Vocabulary List!"'},"​")],-1);function d(m,_,p,u,y,f){const a=o;return c(),r("div",null,[n,s(a,{readTime:"1",words:"5"})])}const V=t(l,[["render",d]]);export{v as __pageData,V as default}; +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as c,c as r,H as s,k as e,a as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Welcome to My Vocabulary List!","description":"","frontmatter":{},"headers":[],"relativePath":"academic/vocabulary/index.md","filePath":"academic/vocabulary/index.md","lastUpdated":1699051935000}'),l={name:"academic/vocabulary/index.md"},n=e("h1",{id:"welcome-to-my-vocabulary-list",tabindex:"-1"},[i("Welcome to My Vocabulary List! "),e("a",{class:"header-anchor",href:"#welcome-to-my-vocabulary-list","aria-label":'Permalink to "Welcome to My Vocabulary List!"'},"​")],-1);function d(m,_,p,u,y,f){const a=o;return c(),r("div",null,[n,s(a,{readTime:"1",words:"5"})])}const V=t(l,[["render",d]]);export{v as __pageData,V as default}; diff --git a/assets/app.6020b1dd.js b/assets/app.11c168a7.js similarity index 99% rename from assets/app.6020b1dd.js rename to assets/app.11c168a7.js index a4464355..71ade6f8 100644 --- a/assets/app.6020b1dd.js +++ b/assets/app.11c168a7.js @@ -1,4 +1,4 @@ -import{d as pt,o as ut,b as qt,l as mr,u as hn,h as vr,C as Ft,w as wr,k as Ze,t as Pr,p as Gr,m as Qr,a as Mr,_ as Jr,M as Zr,a0 as qr,c as Ct,r as fr,n as Tt,g as bt,N as ma,x as jr,j as ja,a1 as ei,R as ti,B as ai,z as ni,e as ar,H as wa,a2 as ri,a3 as ii,a4 as Ar,a5 as Er,a6 as oi,a7 as xa,K as si,O as ui,s as cr,a8 as di,a9 as li,aa as mi,ab as fi,ac as ci,ad as hi,ae as vi,af as _i,ag as gi,ah as pi,U as Pi,y as Mi,ai as Ei,aj as yi,ak as Di}from"./chunks/framework.b7580407.js";import{_ as Oi,t as yr}from"./chunks/theme.7de1b093.js";import{c as ua,g as vn}from"./chunks/commonjsHelpers.725317a4.js";/*! medium-zoom 1.0.8 | MIT License | https://github.com/francoischalifour/medium-zoom */var Zt=Object.assign||function(I){for(var F=1;F1&&arguments[1]!==void 0?arguments[1]:{},n=window.Promise||function(P){function W(){}P(W,W)},e=function(P){var W=P.target;if(W===R){c();return}y.indexOf(W)!==-1&&p({target:W})},t=function(){if(!(T||!U.original)){var P=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(L-P)>h.scrollOffset&&setTimeout(c,150)}},a=function(P){var W=P.key||P.keyCode;(W==="Escape"||W==="Esc"||W===27)&&c()},r=function(){var P=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},W=P;if(P.background&&(R.style.background=P.background),P.container&&P.container instanceof Object&&(W.container=Zt({},h.container,P.container)),P.template){var b=mn(P.template)?P.template:document.querySelector(P.template);W.template=b}return h=Zt({},h,W),y.forEach(function(A){A.dispatchEvent(sa("medium-zoom:update",{detail:{zoom:B}}))}),B},i=function(){var P=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};return I(Zt({},h,P))},o=function(){for(var P=arguments.length,W=Array(P),b=0;b0?W.reduce(function(Y,J){return[].concat(Y,Or(J))},[]):y;return A.forEach(function(Y){Y.classList.remove("medium-zoom-image"),Y.dispatchEvent(sa("medium-zoom:detach",{detail:{zoom:B}}))}),y=y.filter(function(Y){return A.indexOf(Y)===-1}),B},u=function(P,W){var b=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return y.forEach(function(A){A.addEventListener("medium-zoom:"+P,W,b)}),g.push({type:"medium-zoom:"+P,listener:W,options:b}),B},l=function(P,W){var b=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return y.forEach(function(A){A.removeEventListener("medium-zoom:"+P,W,b)}),g=g.filter(function(A){return!(A.type==="medium-zoom:"+P&&A.listener.toString()===W.toString())}),B},f=function(){var P=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},W=P.target,b=function(){var Y={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},J=void 0,Me=void 0;if(h.container)if(h.container instanceof Object)Y=Zt({},Y,h.container),J=Y.width-Y.left-Y.right-h.margin*2,Me=Y.height-Y.top-Y.bottom-h.margin*2;else{var Pe=mn(h.container)?h.container:document.querySelector(h.container),xe=Pe.getBoundingClientRect(),we=xe.width,We=xe.height,Oe=xe.left,Le=xe.top;Y=Zt({},Y,{width:we,height:We,left:Oe,top:Le})}J=J||Y.width-h.margin*2,Me=Me||Y.height-h.margin*2;var ne=U.zoomedHd||U.original,ee=Dr(ne)?J:ne.naturalWidth||J,de=Dr(ne)?Me:ne.naturalHeight||Me,ve=ne.getBoundingClientRect(),ue=ve.top,C=ve.left,K=ve.width,Q=ve.height,V=Math.min(Math.max(K,ee),J)/K,ie=Math.min(Math.max(Q,de),Me)/Q,$=Math.min(V,ie),le=(-C+(J-K)/2+h.margin+Y.left)/$,pe=(-ue+(Me-Q)/2+h.margin+Y.top)/$,_e="scale("+$+") translate3d("+le+"px, "+pe+"px, 0)";U.zoomed.style.transform=_e,U.zoomedHd&&(U.zoomedHd.style.transform=_e)};return new n(function(A){if(W&&y.indexOf(W)===-1){A(B);return}var Y=function we(){T=!1,U.zoomed.removeEventListener("transitionend",we),U.original.dispatchEvent(sa("medium-zoom:opened",{detail:{zoom:B}})),A(B)};if(U.zoomed){A(B);return}if(W)U.original=W;else if(y.length>0){var J=y;U.original=J[0]}else{A(B);return}if(U.original.dispatchEvent(sa("medium-zoom:open",{detail:{zoom:B}})),L=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,T=!0,U.zoomed=Ti(U.original),document.body.appendChild(R),h.template){var Me=mn(h.template)?h.template:document.querySelector(h.template);U.template=document.createElement("div"),U.template.appendChild(Me.content.cloneNode(!0)),document.body.appendChild(U.template)}if(U.original.parentElement&&U.original.parentElement.tagName==="PICTURE"&&U.original.currentSrc&&(U.zoomed.src=U.original.currentSrc),document.body.appendChild(U.zoomed),window.requestAnimationFrame(function(){document.body.classList.add("medium-zoom--opened")}),U.original.classList.add("medium-zoom-image--hidden"),U.zoomed.classList.add("medium-zoom-image--opened"),U.zoomed.addEventListener("click",c),U.zoomed.addEventListener("transitionend",Y),U.original.getAttribute("data-zoom-src")){U.zoomedHd=U.zoomed.cloneNode(),U.zoomedHd.removeAttribute("srcset"),U.zoomedHd.removeAttribute("sizes"),U.zoomedHd.removeAttribute("loading"),U.zoomedHd.src=U.zoomed.getAttribute("data-zoom-src"),U.zoomedHd.onerror=function(){clearInterval(Pe),console.warn("Unable to reach the zoom image target "+U.zoomedHd.src),U.zoomedHd=null,b()};var Pe=setInterval(function(){U.zoomedHd.complete&&(clearInterval(Pe),U.zoomedHd.classList.add("medium-zoom-image--opened"),U.zoomedHd.addEventListener("click",c),document.body.appendChild(U.zoomedHd),b())},10)}else if(U.original.hasAttribute("srcset")){U.zoomedHd=U.zoomed.cloneNode(),U.zoomedHd.removeAttribute("sizes"),U.zoomedHd.removeAttribute("loading");var xe=U.zoomedHd.addEventListener("load",function(){U.zoomedHd.removeEventListener("load",xe),U.zoomedHd.classList.add("medium-zoom-image--opened"),U.zoomedHd.addEventListener("click",c),document.body.appendChild(U.zoomedHd),b()})}else b()})},c=function(){return new n(function(P){if(T||!U.original){P(B);return}var W=function b(){U.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(U.zoomed),U.zoomedHd&&document.body.removeChild(U.zoomedHd),document.body.removeChild(R),U.zoomed.classList.remove("medium-zoom-image--opened"),U.template&&document.body.removeChild(U.template),T=!1,U.zoomed.removeEventListener("transitionend",b),U.original.dispatchEvent(sa("medium-zoom:closed",{detail:{zoom:B}})),U.original=null,U.zoomed=null,U.zoomedHd=null,U.template=null,P(B)};T=!0,document.body.classList.remove("medium-zoom--opened"),U.zoomed.style.transform="",U.zoomedHd&&(U.zoomedHd.style.transform=""),U.template&&(U.template.style.transition="opacity 150ms",U.template.style.opacity=0),U.original.dispatchEvent(sa("medium-zoom:close",{detail:{zoom:B}})),U.zoomed.addEventListener("transitionend",W)})},p=function(){var P=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},W=P.target;return U.original?c():f({target:W})},_=function(){return h},M=function(){return y},D=function(){return U.original},y=[],g=[],T=!1,L=0,h=m,U={original:null,zoomed:null,zoomedHd:null,template:null};Object.prototype.toString.call(F)==="[object Object]"?h=F:(F||typeof F=="string")&&o(F),h=Zt({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},h);var R=Wi(h.background);document.addEventListener("click",e),document.addEventListener("keyup",a),document.addEventListener("scroll",t),window.addEventListener("resize",c);var B={open:f,close:c,toggle:p,update:r,clone:i,attach:o,detach:s,on:u,off:l,getOptions:_,getImages:M,getZoomedImage:D};return B};function xi(I,F){F===void 0&&(F={});var m=F.insertAt;if(!(!I||typeof document>"u")){var n=document.head||document.getElementsByTagName("head")[0],e=document.createElement("style");e.type="text/css",m==="top"&&n.firstChild?n.insertBefore(e,n.firstChild):n.appendChild(e),e.styleSheet?e.styleSheet.cssText=I:e.appendChild(document.createTextNode(I))}}var wi=".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}";xi(wi);const ji=Ci;var Ir={exports:{}};(function(I,F){(function(m,n){I.exports=n()})(ua,function(){var m=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof ua<"u"?ua:typeof self<"u"?self:{},n={exports:{}};/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress * @license MIT */(function(t,a){(function(r,i){t.exports=i()})(m,function(){var r={};r.version="0.2.0";var i=r.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
    '};r.configure=function(y){var g,T;for(g in y)T=y[g],T!==void 0&&y.hasOwnProperty(g)&&(i[g]=T);return this},r.status=null,r.set=function(y){var g=r.isStarted();y=o(y,i.minimum,1),r.status=y===1?null:y;var T=r.render(!g),L=T.querySelector(i.barSelector),h=i.speed,U=i.easing;return T.offsetWidth,l(function(R){i.positionUsing===""&&(i.positionUsing=r.getPositioningCSS()),f(L,u(y,h,U)),y===1?(f(T,{transition:"none",opacity:1}),T.offsetWidth,setTimeout(function(){f(T,{transition:"all "+h+"ms linear",opacity:0}),setTimeout(function(){r.remove(),R()},h)},h)):setTimeout(R,h)}),this},r.isStarted=function(){return typeof r.status=="number"},r.start=function(){r.status||r.set(0);var y=function(){setTimeout(function(){!r.status||(r.trickle(),y())},i.trickleSpeed)};return i.trickle&&y(),this},r.done=function(y){return!y&&!r.status?this:r.inc(.3+.5*Math.random()).set(1)},r.inc=function(y){var g=r.status;return g?(typeof y!="number"&&(y=(1-g)*o(Math.random()*g,.1,.95)),g=o(g+y,0,.994),r.set(g)):r.start()},r.trickle=function(){return r.inc(Math.random()*i.trickleRate)},function(){var y=0,g=0;r.promise=function(T){return!T||T.state()==="resolved"?this:(g===0&&r.start(),y++,g++,T.always(function(){g--,g===0?(y=0,r.done()):r.set((y-g)/y)}),this)}}(),r.render=function(y){if(r.isRendered())return document.getElementById("nprogress");p(document.documentElement,"nprogress-busy");var g=document.createElement("div");g.id="nprogress",g.innerHTML=i.template;var T=g.querySelector(i.barSelector),L=y?"-100":s(r.status||0),h=document.querySelector(i.parent),U;return f(T,{transition:"all 0 linear",transform:"translate3d("+L+"%,0,0)"}),i.showSpinner||(U=g.querySelector(i.spinnerSelector),U&&D(U)),h!=document.body&&p(h,"nprogress-custom-parent"),h.appendChild(g),g},r.remove=function(){_(document.documentElement,"nprogress-busy"),_(document.querySelector(i.parent),"nprogress-custom-parent");var y=document.getElementById("nprogress");y&&D(y)},r.isRendered=function(){return!!document.getElementById("nprogress")},r.getPositioningCSS=function(){var y=document.body.style,g="WebkitTransform"in y?"Webkit":"MozTransform"in y?"Moz":"msTransform"in y?"ms":"OTransform"in y?"O":"";return g+"Perspective"in y?"translate3d":g+"Transform"in y?"translate":"margin"};function o(y,g,T){return yT?T:y}function s(y){return(-1+y)*100}function u(y,g,T){var L;return i.positionUsing==="translate3d"?L={transform:"translate3d("+s(y)+"%,0,0)"}:i.positionUsing==="translate"?L={transform:"translate("+s(y)+"%,0)"}:L={"margin-left":s(y)+"%"},L.transition="all "+g+"ms "+T,L}var l=function(){var y=[];function g(){var T=y.shift();T&&T(g)}return function(T){y.push(T),y.length==1&&g()}}(),f=function(){var y=["Webkit","O","Moz","ms"],g={};function T(R){return R.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(B,z){return z.toUpperCase()})}function L(R){var B=document.body.style;if(R in B)return R;for(var z=y.length,P=R.charAt(0).toUpperCase()+R.slice(1),W;z--;)if(W=y[z]+P,W in B)return W;return R}function h(R){return R=T(R),g[R]||(g[R]=L(R))}function U(R,B,z){B=h(B),R.style[B]=z}return function(R,B){var z=arguments,P,W;if(z.length==2)for(P in B)W=B[P],W!==void 0&&B.hasOwnProperty(P)&&U(R,P,W);else U(R,z[1],z[2])}}();function c(y,g){var T=typeof y=="string"?y:M(y);return T.indexOf(" "+g+" ")>=0}function p(y,g){var T=M(y),L=T+g;c(T,g)||(y.className=L.substring(1))}function _(y,g){var T=M(y),L;!c(y,g)||(L=T.replace(" "+g+" "," "),y.className=L.substring(1,L.length-1))}function M(y){return(" "+(y.className||"")+" ").replace(/\s+/gi," ")}function D(y){y&&y.parentNode&&y.parentNode.removeChild(y)}return r})})(n);const e=n.exports;return t=>{if(typeof window>"u")return;const{router:a}=t;return setTimeout(()=>{e.configure({showSpinner:!1});const r=a.onBeforeRouteChange,i=a.onAfterRouteChanged;a.onBeforeRouteChange=o=>{e.start(),r==null||r(o)},a.onAfterRouteChanged=o=>{e.done(),i==null||i(o)}}),e}})})(Ir);var Ai=Ir.exports;const Ii=vn(Ai);const Li=pt({__name:"AsideSponsors",setup(I){const F=[{items:[{img:"https://jsd.toshiki.dev/gh/andatoshiki/toshiki-notebook@master/assets/logo/sponsor/telegram.png"}]}];return(m,n)=>(ut(),qt(mr(Oi),{data:F}))}});const Aa=I=>(Gr("data-v-ddda9334"),I=I(),Qr(),I),Ri={class:"copyright"},Ui={class:"content"},Si={class:"item"},Bi=Aa(()=>Ze("svg",{class:"icon",width:"20",height:"20",viewBox:"0 0 1024 1024"},[Ze("title",null,"original author"),Ze("path",{d:"M614.72 554.538c-49.086-6.399-100.27-2.1-149.256-2.1-119.465 0-209.04 95.972-206.84 215.437 0 17.095 8.498 31.99 23.493 40.488 14.896 10.697 34.09 14.896 53.285 17.095 61.882 6.398 123.664 6.398 198.342 6.398 40.488 0 93.872-2.1 142.858-4.298 27.692 0 53.284-4.3 78.877-14.896 19.194-8.498 29.89-19.194 31.99-40.488 8.498-104.57-72.478-204.84-172.75-217.636zM680.8 375.39c0-87.474-74.678-162.053-164.251-162.053-89.574 0-162.053 74.679-162.053 162.053-2.1 87.474 74.678 164.252 162.053 164.252 89.673 0 164.252-74.678 164.252-164.252z",fill:"#FFF"}),Ze("path",{d:"M512.35 0C228.733 0 .5 228.233.5 511.85s228.233 511.85 511.85 511.85 511.85-228.233 511.85-511.85S795.967 0 512.35 0zm275.12 772.074c-2.1 21.294-12.797 31.99-31.991 40.488-25.593 10.697-51.185 14.896-78.877 14.896-49.086 2.099-102.37 4.298-142.858 4.298-74.678 0-136.46 0-198.342-6.398-19.195-2.1-38.389-6.398-53.285-17.095-14.895-8.497-23.493-23.493-23.493-40.488-2.1-119.465 87.475-215.437 206.84-215.437 49.085 0 100.27-4.299 149.256 2.1 100.27 12.896 181.247 113.166 172.75 217.636zM354.495 375.39c0-87.474 72.479-162.053 162.053-162.053S680.8 288.016 680.8 375.39c0 89.574-74.679 164.252-164.252 164.252-87.375 0-164.152-76.778-162.053-164.252z",fill:"#249FF8"})],-1)),Ki=Aa(()=>Ze("span",{class:"copyrightText"},"Author: ",-1)),Ni={class:"item"},zi=Aa(()=>Ze("svg",{class:"icon",width:"20",height:"20",viewBox:"0 0 1024 1024"},[Ze("title",null,"Original Link"),Ze("path",{d:"M511.854 0A511.854 511.854 0 1 0 1024 511.854 511.854 511.854 0 0 0 511.854 0z",fill:"#39B54A"}),Ze("path",{d:"M576.491 630.355L460.028 746.818a129.565 129.565 0 0 1-182.555 0l-2.038-2.038a128.983 128.983 0 0 1 0-182.264l81.233-81.233a179.644 179.644 0 0 0 13.102 70.46l-52.7 52.408a69.878 69.878 0 0 0 0 98.703l2.038 2.038a70.169 70.169 0 0 0 98.703 0l116.463-116.463a69.878 69.878 0 0 0 0-98.703l-2.039-2.038a69.587 69.587 0 0 0-13.975-10.772l42.509-42.51a128.11 128.11 0 0 1 13.102 11.356l2.038 2.038a129.274 129.274 0 0 1 0 182.264z",fill:"#FFF"}),Ze("path",{d:"M746.236 460.902l-81.233 81.233a179.353 179.353 0 0 0-13.102-70.46l52.7-52.409a69.878 69.878 0 0 0 0-98.702l-2.039-2.038a69.878 69.878 0 0 0-98.702 0L487.397 434.989a69.878 69.878 0 0 0 0 98.702l2.038 2.038a68.422 68.422 0 0 0 13.976 10.773l-42.51 42.51a136.553 136.553 0 0 1-13.101-11.356l-2.038-2.038a128.983 128.983 0 0 1 0-182.265l116.463-116.462a129.565 129.565 0 0 1 182.555 0l2.038 2.038a128.983 128.983 0 0 1 0 182.264z",fill:"#FFF"})],-1)),ki=Aa(()=>Ze("span",{class:"copyrightText"},"Link: ",-1)),Fi=["href"],Hi=Aa(()=>Ze("div",{class:"item"},[Ze("svg",{class:"icon",width:"20",height:"20",viewBox:"0 0 1024 1024"},[Ze("title",null,"documentation license"),Ze("path",{d:"M0 512a512 512 0 1 0 1024 0A512 512 0 1 0 0 512z",fill:"#F3B243"}),Ze("path",{d:"M540.672 323.584a90.112 90.112 0 1 0 180.224 0 90.112 90.112 0 1 0-180.224 0zM540.672 688.128a90.112 90.112 0 1 0 180.224 0 90.112 90.112 0 1 0-180.224 0zM229.376 512a90.112 90.112 0 1 0 180.224 0 90.112 90.112 0 1 0-180.224 0z",fill:"#FFF"}),Ze("path",{d:"M341.037 480.37l257.344-175.718 27.713 40.592-257.34 175.718z",fill:"#FFF"}),Ze("path",{d:"M349.053 488.452L601.907 670.56l-28.725 39.887L320.307 528.34z",fill:"#FFF"})]),Ze("span",{class:"copyrightText"},"Licensing: "),Ze("span",null,[Mr(" This documentation and all content contained herein, including but not limited to text, graphics, images, and logos, are licensed under "),Ze("a",{href:"https://creativecommons.org/licenses/by-nc-sa/4.0/",rel:"noreferrer",target:"_blank"},"CC BY-NC 4.0"),Mr(", unless specifically noted, attribute the source when reprint. ")])],-1)),Yi="Anda Toshiki (安田俊樹)",Vi="https://www.toshiki.dev",Xi=pt({__name:"Copyright",setup(I){var e,t;const{frontmatter:F}=hn(),m=vr(Yi);(e=F.value)!=null&&e.author&&(m.value=(t=F.value)==null?void 0:t.author);const n=location.href;return(a,r)=>{const i=Ft("ClientOnly");return ut(),qt(i,null,{default:wr(()=>[Ze("div",Ri,[Ze("div",Ui,[Ze("div",Si,[Bi,Ki,Ze("span",null,[Ze("a",{href:Vi,rel:"noreferrer",target:"_blank"},Pr(m.value),1)])]),Ze("div",Ni,[zi,ki,Ze("span",null,[Ze("a",{href:mr(n),rel:"noreferrer",target:"_blank"},Pr(mr(n)),9,Fi)])]),Hi])])]),_:1})}}});const $i=Jr(Xi,[["__scopeId","data-v-ddda9334"]]);var Lr={exports:{}};(function(I){(function(F){function m(T,L){var h=(T&65535)+(L&65535),U=(T>>16)+(L>>16)+(h>>16);return U<<16|h&65535}function n(T,L){return T<>>32-L}function e(T,L,h,U,R,B){return m(n(m(m(L,T),m(U,B)),R),h)}function t(T,L,h,U,R,B,z){return e(L&h|~L&U,T,L,R,B,z)}function a(T,L,h,U,R,B,z){return e(L&U|h&~U,T,L,R,B,z)}function r(T,L,h,U,R,B,z){return e(L^h^U,T,L,R,B,z)}function i(T,L,h,U,R,B,z){return e(h^(L|~U),T,L,R,B,z)}function o(T,L){T[L>>5]|=128<>>9<<4)+14]=L;var h,U,R,B,z,P=1732584193,W=-271733879,b=-1732584194,A=271733878;for(h=0;h>5]>>>L%32&255);return h}function u(T){var L,h=[];for(h[(T.length>>2)-1]=void 0,L=0;L>5]|=(T.charCodeAt(L/8)&255)<16&&(U=o(U,T.length*8)),h=0;h<16;h+=1)R[h]=U[h]^909522486,B[h]=U[h]^1549556828;return z=o(R.concat(u(L)),512+L.length*8),s(o(B.concat(z),512+128))}function c(T){var L="0123456789abcdef",h="",U,R;for(R=0;R>>4&15)+L.charAt(U&15);return h}function p(T){return unescape(encodeURIComponent(T))}function _(T){return l(p(T))}function M(T){return c(_(T))}function D(T,L){return f(p(T),p(L))}function y(T,L){return c(D(T,L))}function g(T,L,h){return L?h?D(L,T):y(L,T):h?_(T):M(T)}I.exports?I.exports=g:F.md5=g})(ua)})(Lr);var Gi=Lr.exports;const Qi=vn(Gi);var Rr={exports:{}};/*! diff --git a/assets/application_markdown-it-katex_how-to-use.md.b10dd06e.js b/assets/application_markdown-it-katex_how-to-use.md.b10dd06e.js new file mode 100644 index 00000000..5f46d957 --- /dev/null +++ b/assets/application_markdown-it-katex_how-to-use.md.b10dd06e.js @@ -0,0 +1,50 @@ +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as p,c as o,H as r,k as s,a,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const x=JSON.parse(`{"title":"@andatoshiki/markdown-it-katex","description":"Documentation for Toshiki's markdown-it-katex fork as an alternative for GitHub readme mirror in case site inaccessibility due to SNI interference by GFW for users in China","frontmatter":{"title":"@andatoshiki/markdown-it-katex","description":"Documentation for Toshiki's markdown-it-katex fork as an alternative for GitHub readme mirror in case site inaccessibility due to SNI interference by GFW for users in China"},"headers":[],"relativePath":"application/markdown-it-katex/how-to-use.md","filePath":"application/markdown-it-katex/how-to-use.md","lastUpdated":1699051935000}`),c={name:"application/markdown-it-katex/how-to-use.md"},i=s("h1",{id:"andatoshiki-markdown-it-katex",tabindex:"-1"},[a("@andatoshiki/markdown-it-katex "),s("a",{class:"header-anchor",href:"#andatoshiki-markdown-it-katex","aria-label":'Permalink to "@andatoshiki/markdown-it-katex"'},"​")],-1),m=s("blockquote",null,[s("p",null,[a("Add graceful "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null,"KaTeX")]),s("annotation",{encoding:"application/x-tex"},"\\KaTeX")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8988em","vertical-align":"-0.2155em"}}),s("span",{class:"mord text"},[s("span",{class:"mord textrm"},"K"),s("span",{class:"mspace",style:{"margin-right":"-0.17em"}}),s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6833em"}},[s("span",{style:{top:"-2.905em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"mord"},[s("span",{class:"mord textrm mtight sizing reset-size6 size3"},"A")])])])])]),s("span",{class:"mspace",style:{"margin-right":"-0.15em"}}),s("span",{class:"mord text"},[s("span",{class:"mord textrm"},"T"),s("span",{class:"mspace",style:{"margin-right":"-0.1667em"}}),s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4678em"}},[s("span",{style:{top:"-2.7845em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord textrm"},"E")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2155em"}},[s("span")])])]),s("span",{class:"mspace",style:{"margin-right":"-0.125em"}}),s("span",{class:"mord textrm"},"X")])])])])]),a(" rendering to your Markdown like a charm with "),s("code",null,"markdown-it"),a(" plugin.")])],-1),d=l(`

    1: Installation

    Before you start using this plugin, make sure you have already installed the default markdown-it parser; if not, please run the following command or refer to the official markdown-it documentation.

    sh
    $ npm install markdown-it --save
    $ npm install markdown-it --save

    First install package with your preferred package manager (npm, yarn, pnpm), or include javascript before the closing </body> for markdown-it-katex's core utils to be loaded for the static page.

    sh
    $ npm install -D @andatoshiki/markdown-it-katex
    $ npm install -D @andatoshiki/markdown-it-katex
    sh
    $ yarn add --dev @andatoshiki/markdown-it-katex
    $ yarn add --dev @andatoshiki/markdown-it-katex
    sh
    $ pnpm add -D @andatoshiki/markdown-it-katex
    $ pnpm add -D @andatoshiki/markdown-it-katex
    html
    <!-- your other body contents ... -->
    +    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    +</body>
    <!-- your other body contents ... -->
    +    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    +</body>

    Including KaTeX CSS is necessary in the way you are convenient with, either link the stylesheet from a third party CDN into the local HTML <head> tag or import it into a currently linked CSS stylesheets to enable styles for KaTeX globally as follows,

    Or, you could clone or download the entire repository source of KaTeX and self load the fonts/styles/scripts locally, but if you prefer loading from third-party CDN with faster load speed when deployed to save your server resources, the following CDN links might be your choice, you can always switch to other platforms based on your need.

    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    html
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    html
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    html
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    html
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    scss
    // ... your other styles
    +@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
    // ... your other styles
    +@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';

    If you are using the default markdown-it parser, I personally recommend that you use the GitHub markdown CSS (github-markdown-css) for styling your HTML output with a similar style replica of GitHub's markdown styling to your familiarity.

    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />

    This forked project maintained by Anda Toshiki comes with the update of KaTeX components with higher style version support (this documentation uses KaTeX version 16.0, without hassels), later versions may works, but no guarantees are given by the developers, if you are not obsessed with the latest released version, 16.0 may fits your need for loading KaTeX on a personal blog site or small educational sites; yet it should work fully functionally.

    Warning

    Since this project is a fork of the original markdown-it-katex project that hasn't been receiving any active updates of its code source for years, the latest katex style version supported is somewhere around ver. 0.9.0 which clearly is outdated and results in broken styles with overflowing and other potential bug presents.

    2: Usage

    RTo render equations, you need to include the markdown-it-katex plugin in the markdown-it components in your JavaScript or TypeScript file as follows,

    js
    var md = require('markdown-it')(),
    +    mk = require('andatoshiki/markdown-it-katex')
    +
    +md.use(mk)
    +
    +// double backslash is required for javascript strings, but not html input
    +var result = md.render('# Math Rulez! \\n  $\\\\sqrt{3x-1}+(1+x)^2$')
    var md = require('markdown-it')(),
    +    mk = require('andatoshiki/markdown-it-katex')
    +
    +md.use(mk)
    +
    +// double backslash is required for javascript strings, but not html input
    +var result = md.render('# Math Rulez! \\n  $\\\\sqrt{3x-1}+(1+x)^2$')
    ts
    import * as mk from 'markdown-it-katex'
    +import * as MarkdownIt from '@andatoshiki/markdown-it'
    +
    +const md = new MarkdownIt()
    +md.use(mk)
    +
    +// double backslash is not required for TypeScript strings or template literals
    +const result = md.render('# Math Rulez! \\n  $\\\\sqrt{3x-1}+(1+x)^2$')
    import * as mk from 'markdown-it-katex'
    +import * as MarkdownIt from '@andatoshiki/markdown-it'
    +
    +const md = new MarkdownIt()
    +md.use(mk)
    +
    +// double backslash is not required for TypeScript strings or template literals
    +const result = md.render('# Math Rulez! \\n  $\\\\sqrt{3x-1}+(1+x)^2$')

    3: Configuration

    The following list of variable are the customizable components of markdown-it-katex, adjust to your needs,

    • katex: You can change KaTeX version by passing the instance.
    • blockClass: Class added to KaTeX block.
    • Apply any other KaTeX options if needed as a regard to the docs
    js
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })

    4: Examples

    4.1: Inline math

    To render your LaTeX equations inline, enclose them with a single dollar sign $ on each side of the equation as follows,

    tex
    $\\sqrt{3x-1}+(1+x)^2$
    $\\sqrt{3x-1}+(1+x)^2$
    `,23),y=s("p",null,[a("rendered output equation as follows, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msqrt",null,[s("mrow",null,[s("mn",null,"3"),s("mi",null,"x"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"+"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\sqrt{3x-1}+(1+x)^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.04em","vertical-align":"-0.1744em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8656em"}},[s("span",{class:"svg-align",style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{"padding-left":"0.833em"}},[s("span",{class:"mord"},"3"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1")])]),s("span",{style:{top:"-2.8256em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"hide-tail",style:{"min-width":"0.853em",height:"1.08em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.08em",viewBox:"0 0 400000 1080",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M95,702 +c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14 +c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54 +c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10 +s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429 +c69,-144,104.5,-217.7,106.5,-221 +l0 -0 +c5.3,-9.3,12,-14,20,-14 +H400000v40H845.2724 +s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7 +c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z +M834 80h400000v40h-400000z`})])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1744em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(".")],-1),h=l(`

    4.2: Blocked math

    To render blocks, use double dollar sign ($$). This mode utilizes larger symbols and centers the result as a block displayed as a <div> block in HTML output, as follows,

    tex
    $$
    +\\frac {\\partial^r} {\\partial \\omega^r} \\left(\\frac {y^{\\omega}} {\\omega}\\right)
    += \\left(\\frac {y^{\\omega}} {\\omega}\\right) \\left\\{(\\log y)^r + \\sum_{i=1}^r \\frac {(-1)^ Ir \\cdots (r-i+1) (\\log y)^{ri}} {\\omega^i} \\right\\}
    +$$
    $$
    +\\frac {\\partial^r} {\\partial \\omega^r} \\left(\\frac {y^{\\omega}} {\\omega}\\right)
    += \\left(\\frac {y^{\\omega}} {\\omega}\\right) \\left\\{(\\log y)^r + \\sum_{i=1}^r \\frac {(-1)^ Ir \\cdots (r-i+1) (\\log y)^{ri}} {\\omega^i} \\right\\}
    +$$

    the above block equation renders the LaTeX equation as a block with output as follows,

    `,4),u=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"∂"),s("mi",null,"r")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"∂"),s("msup",null,[s("mi",null,"ω"),s("mi",null,"r")])])]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mfrac",null,[s("msup",null,[s("mi",null,"y"),s("mi",null,"ω")]),s("mi",null,"ω")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("mfrac",null,[s("msup",null,[s("mi",null,"y"),s("mi",null,"ω")]),s("mi",null,"ω")]),s("mo",{fence:"true"},")")]),s("mrow",null,[s("mo",{fence:"true"},"{"),s("mo",{stretchy:"false"},"("),s("mi",null,"log"),s("mo",null,"⁡"),s("mi",null,"y"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"r")]),s("mo",null,"+"),s("munderover",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"1")]),s("mi",null,"r")]),s("mfrac",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mo",null,"−"),s("mn",null,"1"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"I")]),s("mi",null,"r"),s("mo",null,"⋯"),s("mo",{stretchy:"false"},"("),s("mi",null,"r"),s("mo",null,"−"),s("mi",null,"i"),s("mo",null,"+"),s("mn",null,"1"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"log"),s("mo",null,"⁡"),s("mi",null,"y"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mrow",null,[s("mi",null,"r"),s("mi",null,"i")])])]),s("msup",null,[s("mi",null,"ω"),s("mi",null,"i")])]),s("mo",{fence:"true"},"}")])]),s("annotation",{encoding:"application/x-tex"},"\\frac {\\partial^r} {\\partial \\omega^r} \\left(\\frac {y^{\\omega}} {\\omega}\\right) = \\left(\\frac {y^{\\omega}} {\\omega}\\right) \\left\\{(\\log y)^r + \\sum_{i=1}^r \\frac {(-1)^ Ir \\cdots (r-i+1) (\\log y)^{ri}} {\\omega^i} \\right\\} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord",style:{"margin-right":"0.05556em"}},"∂"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5904em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord",style:{"margin-right":"0.05556em"}},"∂"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3414em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"ω")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0277em","vertical-align":"-1.2777em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3414em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"ω")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size4"},"{")]),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("lo"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.6514em"}},[s("span",{style:{top:"-1.8723em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mrel mtight"},"="),s("span",{class:"mord mtight"},"1")])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])]),s("span",{style:{top:"-4.3em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2777em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5183em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7507em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"−"),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8413em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"⋯"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("lo"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size4"},"}")])])])])])])],-1),g=l('

    5: Syntax

    Math parsing in markdown is designed to comply with the "latex-in-markdown" conventions set by Pandoc,

    Anything between two $ characters will be treated as TeX math. The opening $ must have a non-space character immediately to its right, while the closing $ must have a non-space character immediately to its left, and must not be followed immediately by a digit. Thus, $20,000 and $30,000 won’t parse as math. If for some reason you need to enclose text in literal $ characters, backslash-escape them and they won’t be treated as math delimiters.

    • Pandoc. “Pandoc - Pandoc User’s Guide.” Pandoc.org, pandoc.org/MANUAL.html#math. Accessed 2 Mar. 2023.

    6: Supported math syntax

    KaTeX is a popular, open-source math typesetting library that is based on TeX and LaTeX. It is designed to be easy to use, and to provide high-quality mathematical typesetting for web applications, refer to the following pages of the document for the full list of function support in KaTeX.

    Note

    Due to the large number of equations rendered on the next following pages, it might takes time to entirely load the webpage, please be patient if the webpage seems to not respond; or it could be a result of slow network connection to correctly render all the equation that causes broken formulas, refresh the page to proceed.

    ',7);function b(k,v,F,C,A,D){const n=e;return p(),o("div",null,[i,r(n,{readTime:"7",words:"1.1k"}),m,d,y,h,u,g])}const q=t(c,[["render",b]]);export{x as __pageData,q as default}; diff --git a/assets/application_markdown-it-katex_how-to-use.md.e6ab0018.lean.js b/assets/application_markdown-it-katex_how-to-use.md.b10dd06e.lean.js similarity index 76% rename from assets/application_markdown-it-katex_how-to-use.md.e6ab0018.lean.js rename to assets/application_markdown-it-katex_how-to-use.md.b10dd06e.lean.js index 1648ab50..2c916fa6 100644 --- a/assets/application_markdown-it-katex_how-to-use.md.e6ab0018.lean.js +++ b/assets/application_markdown-it-katex_how-to-use.md.b10dd06e.lean.js @@ -1,4 +1,4 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o,c as p,H as r,k as s,a,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const D=JSON.parse(`{"title":"@andatoshiki/markdown-it-katex","description":"Documentation for Toshiki's markdown-it-katex fork as an alternative for GitHub readme mirror in case site inaccessibility due to SNI interference by GFW for users in China","frontmatter":{"title":"@andatoshiki/markdown-it-katex","description":"Documentation for Toshiki's markdown-it-katex fork as an alternative for GitHub readme mirror in case site inaccessibility due to SNI interference by GFW for users in China"},"headers":[],"relativePath":"application/markdown-it-katex/how-to-use.md","filePath":"application/markdown-it-katex/how-to-use.md","lastUpdated":1695377563000}`),c={name:"application/markdown-it-katex/how-to-use.md"},i=s("h1",{id:"andatoshiki-markdown-it-katex",tabindex:"-1"},[a("@andatoshiki/markdown-it-katex "),s("a",{class:"header-anchor",href:"#andatoshiki-markdown-it-katex","aria-label":'Permalink to "@andatoshiki/markdown-it-katex"'},"​")],-1),m=s("blockquote",null,[s("p",null,[a("Add graceful "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null,"KaTeX")]),s("annotation",{encoding:"application/x-tex"},"\\KaTeX")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8988em","vertical-align":"-0.2155em"}}),s("span",{class:"mord text"},[s("span",{class:"mord textrm"},"K"),s("span",{class:"mspace",style:{"margin-right":"-0.17em"}}),s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6833em"}},[s("span",{style:{top:"-2.905em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"mord"},[s("span",{class:"mord textrm mtight sizing reset-size6 size3"},"A")])])])])]),s("span",{class:"mspace",style:{"margin-right":"-0.15em"}}),s("span",{class:"mord text"},[s("span",{class:"mord textrm"},"T"),s("span",{class:"mspace",style:{"margin-right":"-0.1667em"}}),s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4678em"}},[s("span",{style:{top:"-2.7845em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord textrm"},"E")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2155em"}},[s("span")])])]),s("span",{class:"mspace",style:{"margin-right":"-0.125em"}}),s("span",{class:"mord textrm"},"X")])])])])]),a(" rendering to your Markdown like a charm with "),s("code",null,"markdown-it"),a(" plugin.")])],-1),y=l("",23),d=s("p",null,[a("rendered output equation as follows, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msqrt",null,[s("mrow",null,[s("mn",null,"3"),s("mi",null,"x"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"+"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\sqrt{3x-1}+(1+x)^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.04em","vertical-align":"-0.1744em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8656em"}},[s("span",{class:"svg-align",style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{"padding-left":"0.833em"}},[s("span",{class:"mord"},"3"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1")])]),s("span",{style:{top:"-2.8256em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"hide-tail",style:{"min-width":"0.853em",height:"1.08em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.08em",viewBox:"0 0 400000 1080",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M95,702 +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as p,c as o,H as r,k as s,a,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const x=JSON.parse(`{"title":"@andatoshiki/markdown-it-katex","description":"Documentation for Toshiki's markdown-it-katex fork as an alternative for GitHub readme mirror in case site inaccessibility due to SNI interference by GFW for users in China","frontmatter":{"title":"@andatoshiki/markdown-it-katex","description":"Documentation for Toshiki's markdown-it-katex fork as an alternative for GitHub readme mirror in case site inaccessibility due to SNI interference by GFW for users in China"},"headers":[],"relativePath":"application/markdown-it-katex/how-to-use.md","filePath":"application/markdown-it-katex/how-to-use.md","lastUpdated":1699051935000}`),c={name:"application/markdown-it-katex/how-to-use.md"},i=s("h1",{id:"andatoshiki-markdown-it-katex",tabindex:"-1"},[a("@andatoshiki/markdown-it-katex "),s("a",{class:"header-anchor",href:"#andatoshiki-markdown-it-katex","aria-label":'Permalink to "@andatoshiki/markdown-it-katex"'},"​")],-1),m=s("blockquote",null,[s("p",null,[a("Add graceful "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null,"KaTeX")]),s("annotation",{encoding:"application/x-tex"},"\\KaTeX")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8988em","vertical-align":"-0.2155em"}}),s("span",{class:"mord text"},[s("span",{class:"mord textrm"},"K"),s("span",{class:"mspace",style:{"margin-right":"-0.17em"}}),s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6833em"}},[s("span",{style:{top:"-2.905em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"mord"},[s("span",{class:"mord textrm mtight sizing reset-size6 size3"},"A")])])])])]),s("span",{class:"mspace",style:{"margin-right":"-0.15em"}}),s("span",{class:"mord text"},[s("span",{class:"mord textrm"},"T"),s("span",{class:"mspace",style:{"margin-right":"-0.1667em"}}),s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4678em"}},[s("span",{style:{top:"-2.7845em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord textrm"},"E")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2155em"}},[s("span")])])]),s("span",{class:"mspace",style:{"margin-right":"-0.125em"}}),s("span",{class:"mord textrm"},"X")])])])])]),a(" rendering to your Markdown like a charm with "),s("code",null,"markdown-it"),a(" plugin.")])],-1),d=l("",23),y=s("p",null,[a("rendered output equation as follows, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msqrt",null,[s("mrow",null,[s("mn",null,"3"),s("mi",null,"x"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"+"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\sqrt{3x-1}+(1+x)^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.04em","vertical-align":"-0.1744em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8656em"}},[s("span",{class:"svg-align",style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{"padding-left":"0.833em"}},[s("span",{class:"mord"},"3"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1")])]),s("span",{style:{top:"-2.8256em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"hide-tail",style:{"min-width":"0.853em",height:"1.08em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.08em",viewBox:"0 0 400000 1080",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M95,702 c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14 c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54 c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10 @@ -9,4 +9,4 @@ c5.3,-9.3,12,-14,20,-14 H400000v40H845.2724 s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7 c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z -M834 80h400000v40h-400000z`})])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1744em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(".")],-1),h=l("",4),u=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"∂"),s("mi",null,"r")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"∂"),s("msup",null,[s("mi",null,"ω"),s("mi",null,"r")])])]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mfrac",null,[s("msup",null,[s("mi",null,"y"),s("mi",null,"ω")]),s("mi",null,"ω")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("mfrac",null,[s("msup",null,[s("mi",null,"y"),s("mi",null,"ω")]),s("mi",null,"ω")]),s("mo",{fence:"true"},")")]),s("mrow",null,[s("mo",{fence:"true"},"{"),s("mo",{stretchy:"false"},"("),s("mi",null,"log"),s("mo",null,"⁡"),s("mi",null,"y"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"r")]),s("mo",null,"+"),s("munderover",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"1")]),s("mi",null,"r")]),s("mfrac",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mo",null,"−"),s("mn",null,"1"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"I")]),s("mi",null,"r"),s("mo",null,"⋯"),s("mo",{stretchy:"false"},"("),s("mi",null,"r"),s("mo",null,"−"),s("mi",null,"i"),s("mo",null,"+"),s("mn",null,"1"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"log"),s("mo",null,"⁡"),s("mi",null,"y"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mrow",null,[s("mi",null,"r"),s("mi",null,"i")])])]),s("msup",null,[s("mi",null,"ω"),s("mi",null,"i")])]),s("mo",{fence:"true"},"}")])]),s("annotation",{encoding:"application/x-tex"},"\\frac {\\partial^r} {\\partial \\omega^r} \\left(\\frac {y^{\\omega}} {\\omega}\\right) = \\left(\\frac {y^{\\omega}} {\\omega}\\right) \\left\\{(\\log y)^r + \\sum_{i=1}^r \\frac {(-1)^ Ir \\cdots (r-i+1) (\\log y)^{ri}} {\\omega^i} \\right\\} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord",style:{"margin-right":"0.05556em"}},"∂"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5904em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord",style:{"margin-right":"0.05556em"}},"∂"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3414em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"ω")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0277em","vertical-align":"-1.2777em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3414em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"ω")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size4"},"{")]),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("lo"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.6514em"}},[s("span",{style:{top:"-1.8723em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mrel mtight"},"="),s("span",{class:"mord mtight"},"1")])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])]),s("span",{style:{top:"-4.3em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2777em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5183em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7507em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"−"),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8413em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"⋯"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("lo"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size4"},"}")])])])])])])],-1),g=l("",7);function b(k,v,B,A,f,w){const n=e;return o(),p("div",null,[i,r(n,{readTime:"7",words:"1.1k"}),m,y,d,h,u,g])}const _=t(c,[["render",b]]);export{D as __pageData,_ as default}; +M834 80h400000v40h-400000z`})])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1744em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(".")],-1),h=l("",4),u=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"∂"),s("mi",null,"r")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"∂"),s("msup",null,[s("mi",null,"ω"),s("mi",null,"r")])])]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mfrac",null,[s("msup",null,[s("mi",null,"y"),s("mi",null,"ω")]),s("mi",null,"ω")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("mfrac",null,[s("msup",null,[s("mi",null,"y"),s("mi",null,"ω")]),s("mi",null,"ω")]),s("mo",{fence:"true"},")")]),s("mrow",null,[s("mo",{fence:"true"},"{"),s("mo",{stretchy:"false"},"("),s("mi",null,"log"),s("mo",null,"⁡"),s("mi",null,"y"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"r")]),s("mo",null,"+"),s("munderover",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"1")]),s("mi",null,"r")]),s("mfrac",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mo",null,"−"),s("mn",null,"1"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"I")]),s("mi",null,"r"),s("mo",null,"⋯"),s("mo",{stretchy:"false"},"("),s("mi",null,"r"),s("mo",null,"−"),s("mi",null,"i"),s("mo",null,"+"),s("mn",null,"1"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"log"),s("mo",null,"⁡"),s("mi",null,"y"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mrow",null,[s("mi",null,"r"),s("mi",null,"i")])])]),s("msup",null,[s("mi",null,"ω"),s("mi",null,"i")])]),s("mo",{fence:"true"},"}")])]),s("annotation",{encoding:"application/x-tex"},"\\frac {\\partial^r} {\\partial \\omega^r} \\left(\\frac {y^{\\omega}} {\\omega}\\right) = \\left(\\frac {y^{\\omega}} {\\omega}\\right) \\left\\{(\\log y)^r + \\sum_{i=1}^r \\frac {(-1)^ Ir \\cdots (r-i+1) (\\log y)^{ri}} {\\omega^i} \\right\\} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord",style:{"margin-right":"0.05556em"}},"∂"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5904em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord",style:{"margin-right":"0.05556em"}},"∂"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3414em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"ω")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0277em","vertical-align":"-1.2777em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3414em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"ω")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size4"},"{")]),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("lo"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.6514em"}},[s("span",{style:{top:"-1.8723em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mrel mtight"},"="),s("span",{class:"mord mtight"},"1")])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])]),s("span",{style:{top:"-4.3em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2777em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5183em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7507em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"−"),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8413em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"⋯"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("lo"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size4"},"}")])])])])])])],-1),g=l("",7);function b(k,v,F,C,A,D){const n=e;return p(),o("div",null,[i,r(n,{readTime:"7",words:"1.1k"}),m,d,y,h,u,g])}const q=t(c,[["render",b]]);export{x as __pageData,q as default}; diff --git a/assets/application_markdown-it-katex_how-to-use.md.e6ab0018.js b/assets/application_markdown-it-katex_how-to-use.md.e6ab0018.js deleted file mode 100644 index db9f6f8a..00000000 --- a/assets/application_markdown-it-katex_how-to-use.md.e6ab0018.js +++ /dev/null @@ -1,50 +0,0 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o,c as p,H as r,k as s,a,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const D=JSON.parse(`{"title":"@andatoshiki/markdown-it-katex","description":"Documentation for Toshiki's markdown-it-katex fork as an alternative for GitHub readme mirror in case site inaccessibility due to SNI interference by GFW for users in China","frontmatter":{"title":"@andatoshiki/markdown-it-katex","description":"Documentation for Toshiki's markdown-it-katex fork as an alternative for GitHub readme mirror in case site inaccessibility due to SNI interference by GFW for users in China"},"headers":[],"relativePath":"application/markdown-it-katex/how-to-use.md","filePath":"application/markdown-it-katex/how-to-use.md","lastUpdated":1695377563000}`),c={name:"application/markdown-it-katex/how-to-use.md"},i=s("h1",{id:"andatoshiki-markdown-it-katex",tabindex:"-1"},[a("@andatoshiki/markdown-it-katex "),s("a",{class:"header-anchor",href:"#andatoshiki-markdown-it-katex","aria-label":'Permalink to "@andatoshiki/markdown-it-katex"'},"​")],-1),m=s("blockquote",null,[s("p",null,[a("Add graceful "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mtext",null,"KaTeX")]),s("annotation",{encoding:"application/x-tex"},"\\KaTeX")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8988em","vertical-align":"-0.2155em"}}),s("span",{class:"mord text"},[s("span",{class:"mord textrm"},"K"),s("span",{class:"mspace",style:{"margin-right":"-0.17em"}}),s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6833em"}},[s("span",{style:{top:"-2.905em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"mord"},[s("span",{class:"mord textrm mtight sizing reset-size6 size3"},"A")])])])])]),s("span",{class:"mspace",style:{"margin-right":"-0.15em"}}),s("span",{class:"mord text"},[s("span",{class:"mord textrm"},"T"),s("span",{class:"mspace",style:{"margin-right":"-0.1667em"}}),s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4678em"}},[s("span",{style:{top:"-2.7845em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord textrm"},"E")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2155em"}},[s("span")])])]),s("span",{class:"mspace",style:{"margin-right":"-0.125em"}}),s("span",{class:"mord textrm"},"X")])])])])]),a(" rendering to your Markdown like a charm with "),s("code",null,"markdown-it"),a(" plugin.")])],-1),y=l(`

    1: Installation

    Before you start using this plugin, make sure you have already installed the default markdown-it parser; if not, please run the following command or refer to the official markdown-it documentation.

    sh
    $ npm install markdown-it --save
    $ npm install markdown-it --save

    First install package with your preferred package manager (npm, yarn, pnpm), or include javascript before the closing </body> for markdown-it-katex's core utils to be loaded for the static page.

    sh
    $ npm install -D @andatoshiki/markdown-it-katex
    $ npm install -D @andatoshiki/markdown-it-katex
    sh
    $ yarn add --dev @andatoshiki/markdown-it-katex
    $ yarn add --dev @andatoshiki/markdown-it-katex
    sh
    $ pnpm add -D @andatoshiki/markdown-it-katex
    $ pnpm add -D @andatoshiki/markdown-it-katex
    html
    <!-- your other body contents ... -->
    -    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    -</body>
    <!-- your other body contents ... -->
    -    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    -</body>

    Including KaTeX CSS is necessary in the way you are convenient with, either link the stylesheet from a third party CDN into the local HTML <head> tag or import it into a currently linked CSS stylesheets to enable styles for KaTeX globally as follows,

    Or, you could clone or download the entire repository source of KaTeX and self load the fonts/styles/scripts locally, but if you prefer loading from third-party CDN with faster load speed when deployed to save your server resources, the following CDN links might be your choice, you can always switch to other platforms based on your need.

    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    html
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    html
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    html
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    html
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    scss
    // ... your other styles
    -@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
    // ... your other styles
    -@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';

    If you are using the default markdown-it parser, I personally recommend that you use the GitHub markdown CSS (github-markdown-css) for styling your HTML output with a similar style replica of GitHub's markdown styling to your familiarity.

    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />

    This forked project maintained by Anda Toshiki comes with the update of KaTeX components with higher style version support (this documentation uses KaTeX version 16.0, without hassels), later versions may works, but no guarantees are given by the developers, if you are not obsessed with the latest released version, 16.0 may fits your need for loading KaTeX on a personal blog site or small educational sites; yet it should work fully functionally.

    Warning

    Since this project is a fork of the original markdown-it-katex project that hasn't been receiving any active updates of its code source for years, the latest katex style version supported is somewhere around ver. 0.9.0 which clearly is outdated and results in broken styles with overflowing and other potential bug presents.

    2: Usage

    RTo render equations, you need to include the markdown-it-katex plugin in the markdown-it components in your JavaScript or TypeScript file as follows,

    js
    var md = require('markdown-it')(),
    -    mk = require('andatoshiki/markdown-it-katex')
    -
    -md.use(mk)
    -
    -// double backslash is required for javascript strings, but not html input
    -var result = md.render('# Math Rulez! \\n  $\\\\sqrt{3x-1}+(1+x)^2$')
    var md = require('markdown-it')(),
    -    mk = require('andatoshiki/markdown-it-katex')
    -
    -md.use(mk)
    -
    -// double backslash is required for javascript strings, but not html input
    -var result = md.render('# Math Rulez! \\n  $\\\\sqrt{3x-1}+(1+x)^2$')
    ts
    import * as mk from 'markdown-it-katex'
    -import * as MarkdownIt from '@andatoshiki/markdown-it'
    -
    -const md = new MarkdownIt()
    -md.use(mk)
    -
    -// double backslash is not required for TypeScript strings or template literals
    -const result = md.render('# Math Rulez! \\n  $\\\\sqrt{3x-1}+(1+x)^2$')
    import * as mk from 'markdown-it-katex'
    -import * as MarkdownIt from '@andatoshiki/markdown-it'
    -
    -const md = new MarkdownIt()
    -md.use(mk)
    -
    -// double backslash is not required for TypeScript strings or template literals
    -const result = md.render('# Math Rulez! \\n  $\\\\sqrt{3x-1}+(1+x)^2$')

    3: Configuration

    The following list of variable are the customizable components of markdown-it-katex, adjust to your needs,

    • katex: You can change KaTeX version by passing the instance.
    • blockClass: Class added to KaTeX block.
    • Apply any other KaTeX options if needed as a regard to the docs
    js
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })

    4: Examples

    4.1: Inline math

    To render your LaTeX equations inline, enclose them with a single dollar sign $ on each side of the equation as follows,

    tex
    $\\sqrt{3x-1}+(1+x)^2$
    $\\sqrt{3x-1}+(1+x)^2$
    `,23),d=s("p",null,[a("rendered output equation as follows, "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msqrt",null,[s("mrow",null,[s("mn",null,"3"),s("mi",null,"x"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",null,"+"),s("mo",{stretchy:"false"},"("),s("mn",null,"1"),s("mo",null,"+"),s("mi",null,"x"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"\\sqrt{3x-1}+(1+x)^2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.04em","vertical-align":"-0.1744em"}}),s("span",{class:"mord sqrt"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8656em"}},[s("span",{class:"svg-align",style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord",style:{"padding-left":"0.833em"}},[s("span",{class:"mord"},"3"),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1")])]),s("span",{style:{top:"-2.8256em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"hide-tail",style:{"min-width":"0.853em",height:"1.08em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"400em",height:"1.08em",viewBox:"0 0 400000 1080",preserveAspectRatio:"xMinYMin slice"},[s("path",{d:`M95,702 -c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14 -c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54 -c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10 -s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429 -c69,-144,104.5,-217.7,106.5,-221 -l0 -0 -c5.3,-9.3,12,-14,20,-14 -H400000v40H845.2724 -s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7 -c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z -M834 80h400000v40h-400000z`})])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1744em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord"},"1"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0641em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])])])])]),a(".")],-1),h=l(`

    4.2: Blocked math

    To render blocks, use double dollar sign ($$). This mode utilizes larger symbols and centers the result as a block displayed as a <div> block in HTML output, as follows,

    tex
    $$
    -\\frac {\\partial^r} {\\partial \\omega^r} \\left(\\frac {y^{\\omega}} {\\omega}\\right)
    -= \\left(\\frac {y^{\\omega}} {\\omega}\\right) \\left\\{(\\log y)^r + \\sum_{i=1}^r \\frac {(-1)^ Ir \\cdots (r-i+1) (\\log y)^{ri}} {\\omega^i} \\right\\}
    -$$
    $$
    -\\frac {\\partial^r} {\\partial \\omega^r} \\left(\\frac {y^{\\omega}} {\\omega}\\right)
    -= \\left(\\frac {y^{\\omega}} {\\omega}\\right) \\left\\{(\\log y)^r + \\sum_{i=1}^r \\frac {(-1)^ Ir \\cdots (r-i+1) (\\log y)^{ri}} {\\omega^i} \\right\\}
    -$$

    the above block equation renders the LaTeX equation as a block with output as follows,

    `,4),u=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mfrac",null,[s("msup",null,[s("mi",{mathvariant:"normal"},"∂"),s("mi",null,"r")]),s("mrow",null,[s("mi",{mathvariant:"normal"},"∂"),s("msup",null,[s("mi",null,"ω"),s("mi",null,"r")])])]),s("mrow",null,[s("mo",{fence:"true"},"("),s("mfrac",null,[s("msup",null,[s("mi",null,"y"),s("mi",null,"ω")]),s("mi",null,"ω")]),s("mo",{fence:"true"},")")]),s("mo",null,"="),s("mrow",null,[s("mo",{fence:"true"},"("),s("mfrac",null,[s("msup",null,[s("mi",null,"y"),s("mi",null,"ω")]),s("mi",null,"ω")]),s("mo",{fence:"true"},")")]),s("mrow",null,[s("mo",{fence:"true"},"{"),s("mo",{stretchy:"false"},"("),s("mi",null,"log"),s("mo",null,"⁡"),s("mi",null,"y"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"r")]),s("mo",null,"+"),s("munderover",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"1")]),s("mi",null,"r")]),s("mfrac",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mo",null,"−"),s("mn",null,"1"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mi",null,"I")]),s("mi",null,"r"),s("mo",null,"⋯"),s("mo",{stretchy:"false"},"("),s("mi",null,"r"),s("mo",null,"−"),s("mi",null,"i"),s("mo",null,"+"),s("mn",null,"1"),s("mo",{stretchy:"false"},")"),s("mo",{stretchy:"false"},"("),s("mi",null,"log"),s("mo",null,"⁡"),s("mi",null,"y"),s("msup",null,[s("mo",{stretchy:"false"},")"),s("mrow",null,[s("mi",null,"r"),s("mi",null,"i")])])]),s("msup",null,[s("mi",null,"ω"),s("mi",null,"i")])]),s("mo",{fence:"true"},"}")])]),s("annotation",{encoding:"application/x-tex"},"\\frac {\\partial^r} {\\partial \\omega^r} \\left(\\frac {y^{\\omega}} {\\omega}\\right) = \\left(\\frac {y^{\\omega}} {\\omega}\\right) \\left\\{(\\log y)^r + \\sum_{i=1}^r \\frac {(-1)^ Ir \\cdots (r-i+1) (\\log y)^{ri}} {\\omega^i} \\right\\} ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3714em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord",style:{"margin-right":"0.05556em"}},"∂"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.5904em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord",style:{"margin-right":"0.05556em"}},"∂"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3414em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"ω")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0277em","vertical-align":"-1.2777em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"(")]),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.3414em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω")])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6644em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.03588em"}},"ω")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},")")])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size4"},"{")]),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("lo"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7144em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.6514em"}},[s("span",{style:{top:"-1.8723em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mrel mtight"},"="),s("span",{class:"mord mtight"},"1")])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])]),s("span",{style:{top:"-4.3em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2777em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mopen nulldelimiter"}),s("span",{class:"mfrac"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.5183em"}},[s("span",{style:{top:"-2.314em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"ω"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7507em"}},[s("span",{style:{top:"-2.989em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])]),s("span",{style:{top:"-3.23em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),s("span",{style:{top:"-3.677em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mopen"},"("),s("span",{class:"mord"},"−"),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8413em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.07847em"}},"I")])])])])])])]),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"minner"},"⋯"),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"−"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord mathnormal"},"i"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mclose"},")"),s("span",{class:"mopen"},"("),s("span",{class:"mop"},[a("lo"),s("span",{style:{"margin-right":"0.01389em"}},"g")]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},[s("span",{class:"mclose"},")"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8247em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.02778em"}},"r"),s("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.686em"}},[s("span")])])])]),s("span",{class:"mclose nulldelimiter"})]),s("span",{class:"mclose delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size4"},"}")])])])])])])],-1),g=l('

    5: Syntax

    Math parsing in markdown is designed to comply with the "latex-in-markdown" conventions set by Pandoc,

    Anything between two $ characters will be treated as TeX math. The opening $ must have a non-space character immediately to its right, while the closing $ must have a non-space character immediately to its left, and must not be followed immediately by a digit. Thus, $20,000 and $30,000 won’t parse as math. If for some reason you need to enclose text in literal $ characters, backslash-escape them and they won’t be treated as math delimiters.

    • Pandoc. “Pandoc - Pandoc User’s Guide.” Pandoc.org, pandoc.org/MANUAL.html#math. Accessed 2 Mar. 2023.

    6: Supported math syntax

    KaTeX is a popular, open-source math typesetting library that is based on TeX and LaTeX. It is designed to be easy to use, and to provide high-quality mathematical typesetting for web applications, refer to the following pages of the document for the full list of function support in KaTeX.

    Note

    Due to the large number of equations rendered on the next following pages, it might takes time to entirely load the webpage, please be patient if the webpage seems to not respond; or it could be a result of slow network connection to correctly render all the equation that causes broken formulas, refresh the page to proceed.

    ',7);function b(k,v,B,A,f,w){const n=e;return o(),p("div",null,[i,r(n,{readTime:"7",words:"1.1k"}),m,y,d,h,u,g])}const _=t(c,[["render",b]]);export{D as __pageData,_ as default}; diff --git a/assets/application_markdown-it-katex_support-function.md.009fe258.js b/assets/application_markdown-it-katex_support-function.md.59634b4a.js similarity index 99% rename from assets/application_markdown-it-katex_support-function.md.009fe258.js rename to assets/application_markdown-it-katex_support-function.md.59634b4a.js index bb3757be..7959320c 100644 --- a/assets/application_markdown-it-katex_support-function.md.009fe258.js +++ b/assets/application_markdown-it-katex_support-function.md.59634b4a.js @@ -1,4 +1,4 @@ -import{_ as m}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as l,c as n,H as c,k as s,a,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Lt=JSON.parse('{"title":"KaTeX: Supported functions","description":"Supported functions within KaTeX syntaxes.","frontmatter":{"title":"KaTeX: Supported functions","description":"Supported functions within KaTeX syntaxes."},"headers":[],"relativePath":"application/markdown-it-katex/support-function.md","filePath":"application/markdown-it-katex/support-function.md","lastUpdated":1695377563000}'),p={name:"application/markdown-it-katex/support-function.md"},r=s("h1",{id:"katex-supported-function",tabindex:"-1"},[a("KaTeX: Supported function "),s("a",{class:"header-anchor",href:"#katex-supported-function","aria-label":'Permalink to "KaTeX: Supported function"'},"​")],-1),h=t('

    note

    This is an direct shameful copy of the documentation pulled from KaTeX documentation, I do not own any of the content below on behalf of this part of the documentation, the table might be outdated as versions migrates, please also refer to KaTeX's official documentation.

    This following is a list of TeX functions supported by KaTeX. It is sorted into logical groups.

    There is a similar Support Table on the next page, sorted alphabetically in am more intuitive way with the lists both supported and un-supported functions, viewing both tables are suggested comprehensibly and interchangeably is highly suggested.

    1: Accents

    ',4),o=s("thead",null,[s("tr",null,[s("th",{style:{"text-align":"left"}}),s("th",{style:{"text-align":"left"}}),s("th",{style:{"text-align":"left"}})])],-1),u=s("tr",null,[s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"a"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),s("annotation",{encoding:"application/x-tex"},"a'")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])])])])]),a(),s("code",null,"a'")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"a"),s("mo",null,"~")])]),s("annotation",{encoding:"application/x-tex"},"\\tilde{a}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6679em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"a")]),s("span",{style:{top:"-3.35em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.25em"}},[s("span",{class:"mord"},"~")])])])])])])])])]),a(),s("code",null,"\\tilde{a}")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"g"),s("mo",null,"˚")])]),s("annotation",{encoding:"application/x-tex"},"\\mathring{g}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6944em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.3472em"}},[s("span",{class:"mord"},"˚")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])])])])]),a(),s("code",null,"\\mathring{g}")])],-1),d=s("tr",null,[s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"a"),s("mrow",null,[s("mo",{mathvariant:"normal"},"′"),s("mo",{mathvariant:"normal"},"′")])])]),s("annotation",{encoding:"application/x-tex"},"a''")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′′")])])])])])])])])])])]),a(),s("code",null,"a''")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mrow",null,[s("mi",null,"a"),s("mi",null,"c")]),s("mo",{stretchy:"true"},"~")])]),s("annotation",{encoding:"application/x-tex"},"\\widetilde{ac}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7166em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7166em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord mathnormal"},"c")])]),s("span",{class:"svg-align",style:{top:"-3.4306em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{style:{height:"0.286em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"0.286em",viewBox:"0 0 1033 286",preserveAspectRatio:"none"},[s("path",{d:`M344 55.266c-142 0-300.638 81.316-311.5 86.418 +import{_ as m}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as l,c as n,H as c,k as s,a,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Lt=JSON.parse('{"title":"KaTeX: Supported functions","description":"Supported functions within KaTeX syntaxes.","frontmatter":{"title":"KaTeX: Supported functions","description":"Supported functions within KaTeX syntaxes."},"headers":[],"relativePath":"application/markdown-it-katex/support-function.md","filePath":"application/markdown-it-katex/support-function.md","lastUpdated":1699051935000}'),p={name:"application/markdown-it-katex/support-function.md"},r=s("h1",{id:"katex-supported-function",tabindex:"-1"},[a("KaTeX: Supported function "),s("a",{class:"header-anchor",href:"#katex-supported-function","aria-label":'Permalink to "KaTeX: Supported function"'},"​")],-1),h=t('

    note

    This is an direct shameful copy of the documentation pulled from KaTeX documentation, I do not own any of the content below on behalf of this part of the documentation, the table might be outdated as versions migrates, please also refer to KaTeX's official documentation.

    This following is a list of TeX functions supported by KaTeX. It is sorted into logical groups.

    There is a similar Support Table on the next page, sorted alphabetically in am more intuitive way with the lists both supported and un-supported functions, viewing both tables are suggested comprehensibly and interchangeably is highly suggested.

    1: Accents

    ',4),o=s("thead",null,[s("tr",null,[s("th",{style:{"text-align":"left"}}),s("th",{style:{"text-align":"left"}}),s("th",{style:{"text-align":"left"}})])],-1),u=s("tr",null,[s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"a"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),s("annotation",{encoding:"application/x-tex"},"a'")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])])])])]),a(),s("code",null,"a'")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"a"),s("mo",null,"~")])]),s("annotation",{encoding:"application/x-tex"},"\\tilde{a}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6679em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"a")]),s("span",{style:{top:"-3.35em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.25em"}},[s("span",{class:"mord"},"~")])])])])])])])])]),a(),s("code",null,"\\tilde{a}")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"g"),s("mo",null,"˚")])]),s("annotation",{encoding:"application/x-tex"},"\\mathring{g}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6944em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.3472em"}},[s("span",{class:"mord"},"˚")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])])])])]),a(),s("code",null,"\\mathring{g}")])],-1),d=s("tr",null,[s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"a"),s("mrow",null,[s("mo",{mathvariant:"normal"},"′"),s("mo",{mathvariant:"normal"},"′")])])]),s("annotation",{encoding:"application/x-tex"},"a''")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′′")])])])])])])])])])])]),a(),s("code",null,"a''")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mrow",null,[s("mi",null,"a"),s("mi",null,"c")]),s("mo",{stretchy:"true"},"~")])]),s("annotation",{encoding:"application/x-tex"},"\\widetilde{ac}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7166em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7166em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord mathnormal"},"c")])]),s("span",{class:"svg-align",style:{top:"-3.4306em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{style:{height:"0.286em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"0.286em",viewBox:"0 0 1033 286",preserveAspectRatio:"none"},[s("path",{d:`M344 55.266c-142 0-300.638 81.316-311.5 86.418 -8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114 c1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751 diff --git a/assets/application_markdown-it-katex_support-function.md.009fe258.lean.js b/assets/application_markdown-it-katex_support-function.md.59634b4a.lean.js similarity index 99% rename from assets/application_markdown-it-katex_support-function.md.009fe258.lean.js rename to assets/application_markdown-it-katex_support-function.md.59634b4a.lean.js index 4e416f77..42304727 100644 --- a/assets/application_markdown-it-katex_support-function.md.009fe258.lean.js +++ b/assets/application_markdown-it-katex_support-function.md.59634b4a.lean.js @@ -1,4 +1,4 @@ -import{_ as m}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as l,c as n,H as c,k as s,a,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Lt=JSON.parse('{"title":"KaTeX: Supported functions","description":"Supported functions within KaTeX syntaxes.","frontmatter":{"title":"KaTeX: Supported functions","description":"Supported functions within KaTeX syntaxes."},"headers":[],"relativePath":"application/markdown-it-katex/support-function.md","filePath":"application/markdown-it-katex/support-function.md","lastUpdated":1695377563000}'),p={name:"application/markdown-it-katex/support-function.md"},r=s("h1",{id:"katex-supported-function",tabindex:"-1"},[a("KaTeX: Supported function "),s("a",{class:"header-anchor",href:"#katex-supported-function","aria-label":'Permalink to "KaTeX: Supported function"'},"​")],-1),h=t("",4),o=s("thead",null,[s("tr",null,[s("th",{style:{"text-align":"left"}}),s("th",{style:{"text-align":"left"}}),s("th",{style:{"text-align":"left"}})])],-1),u=s("tr",null,[s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"a"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),s("annotation",{encoding:"application/x-tex"},"a'")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])])])])]),a(),s("code",null,"a'")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"a"),s("mo",null,"~")])]),s("annotation",{encoding:"application/x-tex"},"\\tilde{a}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6679em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"a")]),s("span",{style:{top:"-3.35em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.25em"}},[s("span",{class:"mord"},"~")])])])])])])])])]),a(),s("code",null,"\\tilde{a}")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"g"),s("mo",null,"˚")])]),s("annotation",{encoding:"application/x-tex"},"\\mathring{g}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6944em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.3472em"}},[s("span",{class:"mord"},"˚")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])])])])]),a(),s("code",null,"\\mathring{g}")])],-1),d=s("tr",null,[s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"a"),s("mrow",null,[s("mo",{mathvariant:"normal"},"′"),s("mo",{mathvariant:"normal"},"′")])])]),s("annotation",{encoding:"application/x-tex"},"a''")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′′")])])])])])])])])])])]),a(),s("code",null,"a''")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mrow",null,[s("mi",null,"a"),s("mi",null,"c")]),s("mo",{stretchy:"true"},"~")])]),s("annotation",{encoding:"application/x-tex"},"\\widetilde{ac}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7166em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7166em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord mathnormal"},"c")])]),s("span",{class:"svg-align",style:{top:"-3.4306em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{style:{height:"0.286em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"0.286em",viewBox:"0 0 1033 286",preserveAspectRatio:"none"},[s("path",{d:`M344 55.266c-142 0-300.638 81.316-311.5 86.418 +import{_ as m}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as l,c as n,H as c,k as s,a,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Lt=JSON.parse('{"title":"KaTeX: Supported functions","description":"Supported functions within KaTeX syntaxes.","frontmatter":{"title":"KaTeX: Supported functions","description":"Supported functions within KaTeX syntaxes."},"headers":[],"relativePath":"application/markdown-it-katex/support-function.md","filePath":"application/markdown-it-katex/support-function.md","lastUpdated":1699051935000}'),p={name:"application/markdown-it-katex/support-function.md"},r=s("h1",{id:"katex-supported-function",tabindex:"-1"},[a("KaTeX: Supported function "),s("a",{class:"header-anchor",href:"#katex-supported-function","aria-label":'Permalink to "KaTeX: Supported function"'},"​")],-1),h=t("",4),o=s("thead",null,[s("tr",null,[s("th",{style:{"text-align":"left"}}),s("th",{style:{"text-align":"left"}}),s("th",{style:{"text-align":"left"}})])],-1),u=s("tr",null,[s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"a"),s("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),s("annotation",{encoding:"application/x-tex"},"a'")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′")])])])])])])])])])])]),a(),s("code",null,"a'")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"a"),s("mo",null,"~")])]),s("annotation",{encoding:"application/x-tex"},"\\tilde{a}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6679em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6679em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal"},"a")]),s("span",{style:{top:"-3.35em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.25em"}},[s("span",{class:"mord"},"~")])])])])])])])])]),a(),s("code",null,"\\tilde{a}")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mi",null,"g"),s("mo",null,"˚")])]),s("annotation",{encoding:"application/x-tex"},"\\mathring{g}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.6944em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g")]),s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"accent-body",style:{left:"-0.3472em"}},[s("span",{class:"mord"},"˚")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.1944em"}},[s("span")])])])])])])]),a(),s("code",null,"\\mathring{g}")])],-1),d=s("tr",null,[s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"a"),s("mrow",null,[s("mo",{mathvariant:"normal"},"′"),s("mo",{mathvariant:"normal"},"′")])])]),s("annotation",{encoding:"application/x-tex"},"a''")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7519em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7519em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"′′")])])])])])])])])])])]),a(),s("code",null,"a''")]),s("td",{style:{"text-align":"left"}},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mover",{accent:"true"},[s("mrow",null,[s("mi",null,"a"),s("mi",null,"c")]),s("mo",{stretchy:"true"},"~")])]),s("annotation",{encoding:"application/x-tex"},"\\widetilde{ac}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7166em"}}),s("span",{class:"mord accent"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.7166em"}},[s("span",{style:{top:"-3em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"a"),s("span",{class:"mord mathnormal"},"c")])]),s("span",{class:"svg-align",style:{top:"-3.4306em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{style:{height:"0.286em"}},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"0.286em",viewBox:"0 0 1033 286",preserveAspectRatio:"none"},[s("path",{d:`M344 55.266c-142 0-300.638 81.316-311.5 86.418 -8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114 c1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751 diff --git a/assets/application_markdown-it-katex_support-table.md.52b042b8.js b/assets/application_markdown-it-katex_support-table.md.419e3a5e.js similarity index 99% rename from assets/application_markdown-it-katex_support-table.md.52b042b8.js rename to assets/application_markdown-it-katex_support-table.md.419e3a5e.js index 92d796e1..2a6d9fc1 100644 --- a/assets/application_markdown-it-katex_support-table.md.52b042b8.js +++ b/assets/application_markdown-it-katex_support-table.md.419e3a5e.js @@ -1,4 +1,4 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as a,c as l,H as m,k as t,a as s,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const sl=JSON.parse('{"title":"KaTeX: Support table","description":"Supported table of KaTeX syntax ordered alphabetically.","frontmatter":{"title":"KaTeX: Support table","description":"Supported table of KaTeX syntax ordered alphabetically."},"headers":[],"relativePath":"application/markdown-it-katex/support-table.md","filePath":"application/markdown-it-katex/support-table.md","lastUpdated":1695377563000}'),p={name:"application/markdown-it-katex/support-table.md"},r=t("h1",{id:"katex-support-table",tabindex:"-1"},[s("KaTeX: Support table "),t("a",{class:"header-anchor",href:"#katex-support-table","aria-label":'Permalink to "KaTeX: Support table"'},"​")],-1),h=c('

    note

    This is an direct shameful copy of the documentation pulled from KaTeX documentation, I do not own any of the content below on behalf of this part of the documentation, the table might be outdated as versions migrates, please also refer to KaTeX's official documentation.

    Symbols

    ',2),o=t("table",null,[t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"left"}},"Symbol/Function"),t("th",{style:{"text-align":"left"}},"Rendered"),t("th",{style:{"text-align":"left"}},"Source or Comment")])]),t("tbody",null,[t("tr",null,[t("td",{style:{"text-align":"left"}},"!"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"n"),t("mo",{stretchy:"false"},"!")]),t("annotation",{encoding:"application/x-tex"},"n!")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"n"),t("span",{class:"mclose"},"!")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"n!")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\!"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," ⁣"),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\!b")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"-0.1667em"}}),t("span",{class:"mord mathnormal"},"b")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\!b")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"#"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mi",null,"y"),t("mn",null,"2")])]),t("annotation",{encoding:"application/x-tex"},"\\def\\bar#1{#1^2} \\bar{y}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8141em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},"2")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\def\\bar#1{#1^2} \\bar{y}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\#"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"#")]),t("annotation",{encoding:"application/x-tex"},"\\#")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},"#")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"%"),t("td",{style:{"text-align":"left"}}),t("td",{style:{"text-align":"left"}},[t("code",null,"%this is a comment")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\%"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"%")]),t("annotation",{encoding:"application/x-tex"},"\\%")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8056em","vertical-align":"-0.0556em"}}),t("span",{class:"mord"},"%")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"&"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\cr c & d \\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\&"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"&")]),t("annotation",{encoding:"application/x-tex"},"\\&")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"&")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"'"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mrow"),t("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),t("annotation",{encoding:"application/x-tex"},"'")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.7519em"}}),t("span",{class:"mord"},[t("span"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.7519em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mtight"},"′")])])])])])])])])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\'"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˊ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\'{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˊ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\'{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"("),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"(")]),t("annotation",{encoding:"application/x-tex"},"(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"(")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},")"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},")")]),t("annotation",{encoding:"application/x-tex"},")")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},")")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\(…\\)"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mfrac",null,[t("mi",null,"a"),t("mi",null,"b")])])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\(\\frac a b\\)}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6954em"}},[t("span",{style:{top:"-2.655em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b")])])]),t("span",{style:{top:"-3.23em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),t("span",{style:{top:"-3.394em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.345em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\(\\frac a b\\)}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\ b")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace"}," "),t("span",{class:"mord mathnormal"},"b")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\ b")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},'\\"'),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"¨")])]),t("annotation",{encoding:"application/x-tex"},'\\text{\\"{a}}')])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"¨")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,'\\text{\\"{a}}')])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\$"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"$")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\textdollar}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8056em","vertical-align":"-0.0556em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"$")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\,"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\,\\,{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\,\\,{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\."),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˙")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\.{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1389em"}},[t("span",{class:"mord"},"˙")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\.{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\:"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\:\\:{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\:\\:{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\;"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null,"  "),t("mtext",null,"  "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\;\\;{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[s("a"),t("code",null,"\\;\\;{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"_"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msub",null,[t("mi",null,"x"),t("mi",null,"i")])]),t("annotation",{encoding:"application/x-tex"},"x_i")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"x"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.3117em"}},[t("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mathnormal mtight"},"i")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.15em"}},[t("span")])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"x_i")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\_"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"_")]),t("annotation",{encoding:"application/x-tex"},"\\_")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em","vertical-align":"-0.31em"}}),t("span",{class:"mord",style:{"margin-right":"0.02778em"}},"_")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},[s("\\"),t("code",null,"`")]),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˋ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\`{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˋ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\'{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"<"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"<")]),t("annotation",{encoding:"application/x-tex"},"<")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),t("span",{class:"mrel"},"<")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\="),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˉ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\={a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5678em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5678em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˉ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\={a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},">"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,">")]),t("annotation",{encoding:"application/x-tex"},">")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),t("span",{class:"mrel"},">")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\>"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\>\\>{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\>\\>{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"["),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"[")]),t("annotation",{encoding:"application/x-tex"},"[")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"[")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"]"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"]")]),t("annotation",{encoding:"application/x-tex"},"]")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},"]")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"{"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a")]),t("annotation",{encoding:"application/x-tex"},"{a}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"}"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a")]),t("annotation",{encoding:"application/x-tex"},"{a}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\{"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"{")]),t("annotation",{encoding:"application/x-tex"},"\\{")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"{")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\}"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"}")]),t("annotation",{encoding:"application/x-tex"},"\\}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},"}")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"|"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"∣")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\|"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∥")]),t("annotation",{encoding:"application/x-tex"},"\\Vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"∥")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"~"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"no no no breaks")]),t("annotation",{encoding:"application/x-tex"},"\\text{no~no~no~breaks}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"breaks")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{no~no~no~breaks}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\~"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˜")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\~{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"˜")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\~{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\\\"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\\\ c & d\\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"^"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mi",null,"x"),t("mi",null,"i")])]),t("annotation",{encoding:"application/x-tex"},"x^i")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8247em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"x"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8247em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"x^i")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\^"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˆ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\^{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˆ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\^{a}}")])])])],-1),d=t("h2",{id:"a",tabindex:"-1"},[s("A "),t("a",{class:"header-anchor",href:"#a","aria-label":'Permalink to "A"'},"​")],-1),x=t("table",null,[t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"left"}},"Symbol/Function"),t("th",{style:{"text-align":"left"}},"Rendered"),t("th",{style:{"text-align":"left"}},"Source or Comment")])]),t("tbody",null,[t("tr",null,[t("td",{style:{"text-align":"left"}},"\\AA"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"A"),t("mo",null,"˚")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\AA}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.9468em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.9468em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},"A")]),t("span",{style:{top:"-3.2523em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.375em"}},[t("span",{class:"mord"},"˚")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\AA}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\aa"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˚")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\aa}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},"a")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.375em"}},[t("span",{class:"mord"},"˚")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\aa}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\above"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mfrac",{linethickness:"0.2em"},[t("mi",null,"a"),t("mrow",null,[t("mi",null,"b"),t("mo",null,"+"),t("mn",null,"1")])])]),t("annotation",{encoding:"application/x-tex"},"{a \\above{2pt} b+1}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.4458em","vertical-align":"-0.5944em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8514em"}},[t("span",{style:{top:"-2.4639em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b"),t("span",{class:"mbin mtight"},"+"),t("span",{class:"mord mtight"},"1")])])]),t("span",{style:{top:"-3.15em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"frac-line",style:{"border-bottom-width":"0.2em"}})]),t("span",{style:{top:"-3.55em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5944em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a \\above{2pt} b+1}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\abovewithdelims"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\acute"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mi",null,"e"),t("mo",null,"ˊ")])]),t("annotation",{encoding:"application/x-tex"},"\\acute e")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord mathnormal"},"e")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1944em"}},[t("span",{class:"mord"},"ˊ")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\acute e")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\AE"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"Æ")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\AE}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"Æ")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\AE}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ae"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"æ")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\ae}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"æ")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\ae}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alef"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\alef")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alefsym"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\alefsym")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\aleph"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\aleph")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"},align:""}),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{aligned}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},aligned:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mo",null,"="),t("mi",null,"b"),t("mo",null,"+"),t("mi",null,"c")])])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mi",null,"d"),t("mo",null,"+"),t("mi",null,"e")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mo",null,"="),t("mi",null,"f")])])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{aligned}a&=b+c\\\\d+e&=f\\end{aligned}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mbin"},"+"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord mathnormal"},"e")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord mathnormal"},"b"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mbin"},"+"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord mathnormal"},"c")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{aligned}"),t("br"),s("   "),t("code",null,"a&=b+c \\\\"),t("br"),s("   "),t("code",null,"d+e&=f"),t("br"),t("code",null,"\\end{aligned}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},alignat:""}),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{alignedat}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},alignedat:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.25em",columnalign:"right left right left",columnspacing:"0em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"10")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"x"),t("mo",null,"+")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"3")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"y"),t("mo",null,"="),t("mn",null,"2")])])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"3")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"x"),t("mo",null,"+")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"13")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"y"),t("mo",null,"="),t("mn",null,"4")])])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{alignedat}{2}10&x+&3&y=2\\\\3&x+&13&y=4\\end{alignedat}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"10")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"3")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal"},"x"),t("span",{class:"mord"},"+")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal"},"x"),t("span",{class:"mord"},"+")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"3")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"13")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},"2")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},"4")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{alignedat}{2}"),t("br"),s("   "),t("code",null,"10&x+ &3&y = 2 \\\\"),t("br"),s("   "),t("code",null," 3&x+&13&y = 4"),t("br"),t("code",null,"\\end{alignedat}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\allowbreak"),t("td",{style:{"text-align":"left"}}),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\Alpha"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"A")]),t("annotation",{encoding:"application/x-tex"},"\\Alpha")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord mathrm"},"A")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alpha"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"α")]),t("annotation",{encoding:"application/x-tex"},"\\alpha")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\amalg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⨿")]),t("annotation",{encoding:"application/x-tex"},"\\amalg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord"},"⨿")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\And"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"&")]),t("annotation",{encoding:"application/x-tex"},"\\And")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"&")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\and"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[t("a",{href:"https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax",target:"_blank",rel:"noreferrer"},"Deprecated")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ang"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[t("a",{href:"https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax",target:"_blank",rel:"noreferrer"},"Deprecated")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\angl"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\angle"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∠")]),t("annotation",{encoding:"application/x-tex"},"\\angle")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6922em"}}),t("span",{class:"mord"},"∠")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\approx"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≈")]),t("annotation",{encoding:"application/x-tex"},"\\approx")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4831em"}}),t("span",{class:"mrel"},"≈")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\approxeq"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≊")]),t("annotation",{encoding:"application/x-tex"},"\\approxeq")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6633em","vertical-align":"-0.0817em"}}),t("span",{class:"mrel amsrm"},"≊")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arccos"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arccos"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arccos")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mop"},"arccos")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arcctg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arcctg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arcctg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("arcct"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arcsin"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arcsin"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arcsin")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mop"},"arcsin")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arctan"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arctan"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arctan")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6151em"}}),t("span",{class:"mop"},"arctan")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arctg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arctg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arctg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("arct"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("ar"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\argmax"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"arg max"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\argmax")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[t("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"arg"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord mathrm"},"max")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\argmin"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"arg min"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\argmin")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8623em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[t("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"arg"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord mathrm"},"min")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"},array:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{array}{cc}a&b\\\\c&d\\end{array}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{array}{cc}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\array"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arraystretch"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.66em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\def\\arraystretch{1.5}\\begin{array}{cc}a&b\\\\c&d\\end{array}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3.6em","vertical-align":"-1.55em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"2.05em"}},[t("span",{style:{top:"-4.05em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.25em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.55em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"2.05em"}},[t("span",{style:{top:"-4.05em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.25em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.55em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\def\\arraystretch{1.5}"),t("br"),t("code",null,"\\begin{array}{cc}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\Arrowvert"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arrowvert"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ast"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∗")]),t("annotation",{encoding:"application/x-tex"},"\\ast")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4653em"}}),t("span",{class:"mord"},"∗")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\asymp"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≍")]),t("annotation",{encoding:"application/x-tex"},"\\asymp")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4637em"}}),t("span",{class:"mrel"},"≍")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\atop"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mfrac",{linethickness:"0px"},[t("mi",null,"a"),t("mi",null,"b")])]),t("annotation",{encoding:"application/x-tex"},"{a \\atop b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0904em","vertical-align":"-0.345em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.7454em"}},[t("span",{style:{top:"-2.355em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b")])])]),t("span",{style:{top:"-3.144em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.345em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a \\atop b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\atopwithdelims"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})])])],-1),g=t("h2",{id:"b",tabindex:"-1"},[s("B "),t("a",{class:"header-anchor",href:"#b","aria-label":'Permalink to "B"'},"​")],-1),u=t("p",null,[s("| Symbol/Function | Rendered | Source or Comment | | :------------------ | :-------------------------------------------------- | :------------------------------------------------------------------------------------------------ | ------ | | \\backepsilon | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∍")]),t("annotation",{encoding:"application/x-tex"},"\\backepsilon")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mrel amsrm"},"∍")])])]),s(" | | | \\backprime | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"‵")]),t("annotation",{encoding:"application/x-tex"},"\\backprime")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5499em"}}),t("span",{class:"mord amsrm"},"‵")])])]),s(" | | | \\backsim | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∽")]),t("annotation",{encoding:"application/x-tex"},"\\backsim")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.3779em"}}),t("span",{class:"mrel amsrm"},"∽")])])]),s(" | | | \\backsimeq | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋍")]),t("annotation",{encoding:"application/x-tex"},"\\backsimeq")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.464em"}}),t("span",{class:"mrel amsrm"},"⋍")])])]),s(" | | | \\backslash | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"\\")]),t("annotation",{encoding:"application/x-tex"},"\\backslash")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"\\")])])]),s(" | | | \\bar | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mi",null,"y"),t("mo",null,"ˉ")])]),t("annotation",{encoding:"application/x-tex"},"\\bar{y}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.7622em","vertical-align":"-0.1944em"}}),t("span",{class:"mord accent"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5678em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1944em"}},[t("span",{class:"mord"},"ˉ")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.1944em"}},[t("span")])])])])])])]),s(" | "),t("code",null,"\\bar{y}"),s(" | | \\barwedge | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⊼")]),t("annotation",{encoding:"application/x-tex"},"\\barwedge")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8867em","vertical-align":"-0.1944em"}}),t("span",{class:"mord amsrm"},"⊼")])])]),s(" | | | \\Bbb | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"double-struck"},"A"),t("mi",{mathvariant:"double-struck"},"B"),t("mi",{mathvariant:"double-struck"},"C")]),t("annotation",{encoding:"application/x-tex"},"\\Bbb{ABC}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathbb"},"ABC")])])])]),s(" | "),t("code",null,"\\Bbb{ABC}"),t("br"),s("KaTeX supports A-Z & k | | \\Bbbk | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"double-struck"},"k")]),t("annotation",{encoding:"application/x-tex"},"\\Bbbk")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord mathbb"},"k")])])]),s(" | | | \\bbox | "),t("span",{style:{color:"firebrick"}},"Not supported"),s(" | | | \\bcancel | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("menclose",{notation:"downdiagonalstrike"},[t("mn",null,"5")])]),t("annotation",{encoding:"application/x-tex"},"\\bcancel{5}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6444em"}}),t("span",{class:"mord"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8444em"}},[t("span",{style:{top:"-3.0444em"}},[t("span",{class:"pstrut",style:{height:"3.0444em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"5")])]),t("span",{class:"svg-align",style:{top:"-2.8444em"}},[t("span",{class:"pstrut",style:{height:"3.0444em"}}),t("span",{style:{height:"1.0444em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"1.0444em"},[t("line",{x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.2em"}},[t("span")])])])])])])]),s(" | "),t("code",null,"\\bcancel{5}"),s(" | | \\because | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∵")]),t("annotation",{encoding:"application/x-tex"},"\\because")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6922em"}}),t("span",{class:"mrel amsrm"},"∵")])])]),s(" | | | \\begin | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\\\ c & d\\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])]),s(" | "),t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}"),s(" | | \\begingroup | "),t("span",{class:"katex-error",title:"ParseError: KaTeX parse error: Expected '\\endgroup', got '}' at position 14: \\begingroup a}̲"},"\\begingroup a}"),s(" | "),t("code",null,"\\begingroup a}"),s(" | | \\Beta | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"B")]),t("annotation",{encoding:"application/x-tex"},"\\Beta")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord mathrm"},"B")])])]),s(" | | | \\beta | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"β")]),t("annotation",{encoding:"application/x-tex"},"\\beta")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s(" | | | \\beth | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℶ")]),t("annotation",{encoding:"application/x-tex"},"\\beth")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord amsrm"},"ℶ")])])]),s(" | | | \\between | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≬")]),t("annotation",{encoding:"application/x-tex"},"\\between")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0117em","vertical-align":"-0.2558em"}}),t("span",{class:"mrel amsrm"},"≬")])])]),s(" | | | \\bf | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"bold"},"A"),t("mi",{mathvariant:"bold"},"a"),t("mi",{mathvariant:"bold"},"B"),t("mi",{mathvariant:"bold"},"b"),t("mn",{mathvariant:"bold"},"12")]),t("annotation",{encoding:"application/x-tex"},"\\bf AaBb12")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathbf"},"AaBb12")])])])]),s(" | "),t("code",null,"\\bf AaBb12"),s(" | | \\bfseries | "),t("span",{style:{color:"firebrick"}},"Not supported"),s(" | | | \\big | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"1.2em",maxsize:"1.2em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"1.2em",maxsize:"1.2em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\big(\\big)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size1"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size1"},")")])])])]),s(" | "),t("code",null,"\\big(\\big)"),s(" | | \\Big | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"1.8em",maxsize:"1.8em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"1.8em",maxsize:"1.8em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\Big(\\Big)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.8em","vertical-align":"-0.65em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size2"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size2"},")")])])])]),s(" | "),t("code",null,"\\Big(\\Big)"),s(" | | \\bigcap | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋂")]),t("annotation",{encoding:"application/x-tex"},"\\bigcap")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"⋂")])])]),s(" | | | \\bigcirc | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"◯")]),t("annotation",{encoding:"application/x-tex"},"\\bigcirc")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},"◯")])])]),s(" | | | \\bigcup | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋃")]),t("annotation",{encoding:"application/x-tex"},"\\bigcup")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"⋃")])])]),s(" | | | \\bigg | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\bigg(\\bigg)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size3"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size3"},")")])])])]),s(" | "),t("code",null,"\\bigg(\\bigg)"),s(" | | \\Bigg | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\Bigg(\\Bigg)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size4"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size4"},")")])])])]),s(" | "),t("code",null,"\\Bigg(\\Bigg)"),s(" | | \\biggl | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"true",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"(")]),t("annotation",{encoding:"application/x-tex"},"\\biggl(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mopen"},[t("span",{class:"delimsizing size3"},"(")])])])]),s(" | "),t("code",null,"\\biggl("),s(" | | \\Biggl | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"true",stretchy:"true",minsize:"3em",maxsize:"3em"},"(")]),t("annotation",{encoding:"application/x-tex"},"\\Biggl(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mopen"},[t("span",{class:"delimsizing size4"},"(")])])])]),s(" | "),t("code",null,"\\Biggl("),s(" | | \\biggm | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\biggm\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mrel"},[t("span",{class:"delimsizing mult"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.45em"}},[t("span",{class:"pstrut",style:{height:"4.4em"}}),t("span",{style:{width:"0.333em",height:"2.400em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"0.333em",height:"2.400em",viewBox:"0 0 333 2400"},[t("path",{d:`M145 15 v585 v1200 v585 c2.667,10,9.667,15,21,15 +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as a,c as l,H as m,k as t,a as s,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const sl=JSON.parse('{"title":"KaTeX: Support table","description":"Supported table of KaTeX syntax ordered alphabetically.","frontmatter":{"title":"KaTeX: Support table","description":"Supported table of KaTeX syntax ordered alphabetically."},"headers":[],"relativePath":"application/markdown-it-katex/support-table.md","filePath":"application/markdown-it-katex/support-table.md","lastUpdated":1699051935000}'),p={name:"application/markdown-it-katex/support-table.md"},r=t("h1",{id:"katex-support-table",tabindex:"-1"},[s("KaTeX: Support table "),t("a",{class:"header-anchor",href:"#katex-support-table","aria-label":'Permalink to "KaTeX: Support table"'},"​")],-1),h=c('

    note

    This is an direct shameful copy of the documentation pulled from KaTeX documentation, I do not own any of the content below on behalf of this part of the documentation, the table might be outdated as versions migrates, please also refer to KaTeX's official documentation.

    Symbols

    ',2),o=t("table",null,[t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"left"}},"Symbol/Function"),t("th",{style:{"text-align":"left"}},"Rendered"),t("th",{style:{"text-align":"left"}},"Source or Comment")])]),t("tbody",null,[t("tr",null,[t("td",{style:{"text-align":"left"}},"!"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"n"),t("mo",{stretchy:"false"},"!")]),t("annotation",{encoding:"application/x-tex"},"n!")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"n"),t("span",{class:"mclose"},"!")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"n!")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\!"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," ⁣"),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\!b")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"-0.1667em"}}),t("span",{class:"mord mathnormal"},"b")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\!b")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"#"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mi",null,"y"),t("mn",null,"2")])]),t("annotation",{encoding:"application/x-tex"},"\\def\\bar#1{#1^2} \\bar{y}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8141em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},"2")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\def\\bar#1{#1^2} \\bar{y}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\#"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"#")]),t("annotation",{encoding:"application/x-tex"},"\\#")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},"#")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"%"),t("td",{style:{"text-align":"left"}}),t("td",{style:{"text-align":"left"}},[t("code",null,"%this is a comment")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\%"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"%")]),t("annotation",{encoding:"application/x-tex"},"\\%")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8056em","vertical-align":"-0.0556em"}}),t("span",{class:"mord"},"%")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"&"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\cr c & d \\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\&"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"&")]),t("annotation",{encoding:"application/x-tex"},"\\&")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"&")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"'"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mrow"),t("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),t("annotation",{encoding:"application/x-tex"},"'")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.7519em"}}),t("span",{class:"mord"},[t("span"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.7519em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mtight"},"′")])])])])])])])])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\'"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˊ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\'{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˊ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\'{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"("),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"(")]),t("annotation",{encoding:"application/x-tex"},"(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"(")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},")"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},")")]),t("annotation",{encoding:"application/x-tex"},")")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},")")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\(…\\)"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mfrac",null,[t("mi",null,"a"),t("mi",null,"b")])])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\(\\frac a b\\)}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6954em"}},[t("span",{style:{top:"-2.655em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b")])])]),t("span",{style:{top:"-3.23em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),t("span",{style:{top:"-3.394em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.345em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\(\\frac a b\\)}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\ b")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace"}," "),t("span",{class:"mord mathnormal"},"b")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\ b")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},'\\"'),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"¨")])]),t("annotation",{encoding:"application/x-tex"},'\\text{\\"{a}}')])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"¨")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,'\\text{\\"{a}}')])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\$"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"$")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\textdollar}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8056em","vertical-align":"-0.0556em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"$")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\,"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\,\\,{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\,\\,{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\."),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˙")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\.{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1389em"}},[t("span",{class:"mord"},"˙")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\.{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\:"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\:\\:{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\:\\:{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\;"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null,"  "),t("mtext",null,"  "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\;\\;{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[s("a"),t("code",null,"\\;\\;{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"_"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msub",null,[t("mi",null,"x"),t("mi",null,"i")])]),t("annotation",{encoding:"application/x-tex"},"x_i")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"x"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.3117em"}},[t("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mathnormal mtight"},"i")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.15em"}},[t("span")])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"x_i")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\_"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"_")]),t("annotation",{encoding:"application/x-tex"},"\\_")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em","vertical-align":"-0.31em"}}),t("span",{class:"mord",style:{"margin-right":"0.02778em"}},"_")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},[s("\\"),t("code",null,"`")]),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˋ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\`{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˋ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\'{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"<"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"<")]),t("annotation",{encoding:"application/x-tex"},"<")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),t("span",{class:"mrel"},"<")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\="),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˉ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\={a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5678em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5678em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˉ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\={a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},">"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,">")]),t("annotation",{encoding:"application/x-tex"},">")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),t("span",{class:"mrel"},">")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\>"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\>\\>{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\>\\>{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"["),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"[")]),t("annotation",{encoding:"application/x-tex"},"[")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"[")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"]"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"]")]),t("annotation",{encoding:"application/x-tex"},"]")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},"]")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"{"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a")]),t("annotation",{encoding:"application/x-tex"},"{a}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"}"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a")]),t("annotation",{encoding:"application/x-tex"},"{a}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\{"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"{")]),t("annotation",{encoding:"application/x-tex"},"\\{")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"{")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\}"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"}")]),t("annotation",{encoding:"application/x-tex"},"\\}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},"}")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"|"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"∣")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\|"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∥")]),t("annotation",{encoding:"application/x-tex"},"\\Vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"∥")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"~"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"no no no breaks")]),t("annotation",{encoding:"application/x-tex"},"\\text{no~no~no~breaks}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"breaks")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{no~no~no~breaks}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\~"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˜")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\~{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"˜")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\~{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\\\"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\\\ c & d\\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"^"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mi",null,"x"),t("mi",null,"i")])]),t("annotation",{encoding:"application/x-tex"},"x^i")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8247em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"x"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8247em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"x^i")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\^"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˆ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\^{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˆ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\^{a}}")])])])],-1),d=t("h2",{id:"a",tabindex:"-1"},[s("A "),t("a",{class:"header-anchor",href:"#a","aria-label":'Permalink to "A"'},"​")],-1),x=t("table",null,[t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"left"}},"Symbol/Function"),t("th",{style:{"text-align":"left"}},"Rendered"),t("th",{style:{"text-align":"left"}},"Source or Comment")])]),t("tbody",null,[t("tr",null,[t("td",{style:{"text-align":"left"}},"\\AA"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"A"),t("mo",null,"˚")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\AA}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.9468em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.9468em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},"A")]),t("span",{style:{top:"-3.2523em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.375em"}},[t("span",{class:"mord"},"˚")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\AA}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\aa"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˚")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\aa}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},"a")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.375em"}},[t("span",{class:"mord"},"˚")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\aa}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\above"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mfrac",{linethickness:"0.2em"},[t("mi",null,"a"),t("mrow",null,[t("mi",null,"b"),t("mo",null,"+"),t("mn",null,"1")])])]),t("annotation",{encoding:"application/x-tex"},"{a \\above{2pt} b+1}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.4458em","vertical-align":"-0.5944em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8514em"}},[t("span",{style:{top:"-2.4639em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b"),t("span",{class:"mbin mtight"},"+"),t("span",{class:"mord mtight"},"1")])])]),t("span",{style:{top:"-3.15em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"frac-line",style:{"border-bottom-width":"0.2em"}})]),t("span",{style:{top:"-3.55em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5944em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a \\above{2pt} b+1}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\abovewithdelims"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\acute"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mi",null,"e"),t("mo",null,"ˊ")])]),t("annotation",{encoding:"application/x-tex"},"\\acute e")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord mathnormal"},"e")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1944em"}},[t("span",{class:"mord"},"ˊ")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\acute e")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\AE"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"Æ")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\AE}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"Æ")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\AE}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ae"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"æ")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\ae}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"æ")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\ae}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alef"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\alef")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alefsym"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\alefsym")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\aleph"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\aleph")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"},align:""}),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{aligned}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},aligned:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mo",null,"="),t("mi",null,"b"),t("mo",null,"+"),t("mi",null,"c")])])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mi",null,"d"),t("mo",null,"+"),t("mi",null,"e")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mo",null,"="),t("mi",null,"f")])])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{aligned}a&=b+c\\\\d+e&=f\\end{aligned}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mbin"},"+"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord mathnormal"},"e")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord mathnormal"},"b"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mbin"},"+"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord mathnormal"},"c")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{aligned}"),t("br"),s("   "),t("code",null,"a&=b+c \\\\"),t("br"),s("   "),t("code",null,"d+e&=f"),t("br"),t("code",null,"\\end{aligned}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},alignat:""}),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{alignedat}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},alignedat:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.25em",columnalign:"right left right left",columnspacing:"0em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"10")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"x"),t("mo",null,"+")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"3")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"y"),t("mo",null,"="),t("mn",null,"2")])])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"3")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"x"),t("mo",null,"+")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"13")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"y"),t("mo",null,"="),t("mn",null,"4")])])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{alignedat}{2}10&x+&3&y=2\\\\3&x+&13&y=4\\end{alignedat}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"10")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"3")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal"},"x"),t("span",{class:"mord"},"+")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal"},"x"),t("span",{class:"mord"},"+")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"3")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"13")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},"2")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},"4")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{alignedat}{2}"),t("br"),s("   "),t("code",null,"10&x+ &3&y = 2 \\\\"),t("br"),s("   "),t("code",null," 3&x+&13&y = 4"),t("br"),t("code",null,"\\end{alignedat}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\allowbreak"),t("td",{style:{"text-align":"left"}}),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\Alpha"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"A")]),t("annotation",{encoding:"application/x-tex"},"\\Alpha")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord mathrm"},"A")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alpha"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"α")]),t("annotation",{encoding:"application/x-tex"},"\\alpha")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\amalg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⨿")]),t("annotation",{encoding:"application/x-tex"},"\\amalg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord"},"⨿")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\And"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"&")]),t("annotation",{encoding:"application/x-tex"},"\\And")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"&")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\and"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[t("a",{href:"https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax",target:"_blank",rel:"noreferrer"},"Deprecated")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ang"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[t("a",{href:"https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax",target:"_blank",rel:"noreferrer"},"Deprecated")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\angl"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\angle"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∠")]),t("annotation",{encoding:"application/x-tex"},"\\angle")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6922em"}}),t("span",{class:"mord"},"∠")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\approx"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≈")]),t("annotation",{encoding:"application/x-tex"},"\\approx")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4831em"}}),t("span",{class:"mrel"},"≈")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\approxeq"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≊")]),t("annotation",{encoding:"application/x-tex"},"\\approxeq")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6633em","vertical-align":"-0.0817em"}}),t("span",{class:"mrel amsrm"},"≊")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arccos"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arccos"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arccos")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mop"},"arccos")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arcctg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arcctg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arcctg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("arcct"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arcsin"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arcsin"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arcsin")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mop"},"arcsin")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arctan"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arctan"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arctan")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6151em"}}),t("span",{class:"mop"},"arctan")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arctg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arctg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arctg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("arct"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("ar"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\argmax"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"arg max"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\argmax")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[t("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"arg"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord mathrm"},"max")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\argmin"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"arg min"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\argmin")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8623em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[t("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"arg"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord mathrm"},"min")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"},array:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{array}{cc}a&b\\\\c&d\\end{array}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{array}{cc}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\array"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arraystretch"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.66em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\def\\arraystretch{1.5}\\begin{array}{cc}a&b\\\\c&d\\end{array}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3.6em","vertical-align":"-1.55em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"2.05em"}},[t("span",{style:{top:"-4.05em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.25em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.55em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"2.05em"}},[t("span",{style:{top:"-4.05em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.25em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.55em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\def\\arraystretch{1.5}"),t("br"),t("code",null,"\\begin{array}{cc}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\Arrowvert"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arrowvert"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ast"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∗")]),t("annotation",{encoding:"application/x-tex"},"\\ast")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4653em"}}),t("span",{class:"mord"},"∗")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\asymp"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≍")]),t("annotation",{encoding:"application/x-tex"},"\\asymp")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4637em"}}),t("span",{class:"mrel"},"≍")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\atop"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mfrac",{linethickness:"0px"},[t("mi",null,"a"),t("mi",null,"b")])]),t("annotation",{encoding:"application/x-tex"},"{a \\atop b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0904em","vertical-align":"-0.345em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.7454em"}},[t("span",{style:{top:"-2.355em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b")])])]),t("span",{style:{top:"-3.144em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.345em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a \\atop b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\atopwithdelims"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})])])],-1),g=t("h2",{id:"b",tabindex:"-1"},[s("B "),t("a",{class:"header-anchor",href:"#b","aria-label":'Permalink to "B"'},"​")],-1),u=t("p",null,[s("| Symbol/Function | Rendered | Source or Comment | | :------------------ | :-------------------------------------------------- | :------------------------------------------------------------------------------------------------ | ------ | | \\backepsilon | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∍")]),t("annotation",{encoding:"application/x-tex"},"\\backepsilon")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mrel amsrm"},"∍")])])]),s(" | | | \\backprime | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"‵")]),t("annotation",{encoding:"application/x-tex"},"\\backprime")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5499em"}}),t("span",{class:"mord amsrm"},"‵")])])]),s(" | | | \\backsim | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∽")]),t("annotation",{encoding:"application/x-tex"},"\\backsim")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.3779em"}}),t("span",{class:"mrel amsrm"},"∽")])])]),s(" | | | \\backsimeq | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋍")]),t("annotation",{encoding:"application/x-tex"},"\\backsimeq")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.464em"}}),t("span",{class:"mrel amsrm"},"⋍")])])]),s(" | | | \\backslash | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"\\")]),t("annotation",{encoding:"application/x-tex"},"\\backslash")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"\\")])])]),s(" | | | \\bar | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mi",null,"y"),t("mo",null,"ˉ")])]),t("annotation",{encoding:"application/x-tex"},"\\bar{y}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.7622em","vertical-align":"-0.1944em"}}),t("span",{class:"mord accent"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5678em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1944em"}},[t("span",{class:"mord"},"ˉ")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.1944em"}},[t("span")])])])])])])]),s(" | "),t("code",null,"\\bar{y}"),s(" | | \\barwedge | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⊼")]),t("annotation",{encoding:"application/x-tex"},"\\barwedge")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8867em","vertical-align":"-0.1944em"}}),t("span",{class:"mord amsrm"},"⊼")])])]),s(" | | | \\Bbb | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"double-struck"},"A"),t("mi",{mathvariant:"double-struck"},"B"),t("mi",{mathvariant:"double-struck"},"C")]),t("annotation",{encoding:"application/x-tex"},"\\Bbb{ABC}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathbb"},"ABC")])])])]),s(" | "),t("code",null,"\\Bbb{ABC}"),t("br"),s("KaTeX supports A-Z & k | | \\Bbbk | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"double-struck"},"k")]),t("annotation",{encoding:"application/x-tex"},"\\Bbbk")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord mathbb"},"k")])])]),s(" | | | \\bbox | "),t("span",{style:{color:"firebrick"}},"Not supported"),s(" | | | \\bcancel | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("menclose",{notation:"downdiagonalstrike"},[t("mn",null,"5")])]),t("annotation",{encoding:"application/x-tex"},"\\bcancel{5}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6444em"}}),t("span",{class:"mord"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8444em"}},[t("span",{style:{top:"-3.0444em"}},[t("span",{class:"pstrut",style:{height:"3.0444em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"5")])]),t("span",{class:"svg-align",style:{top:"-2.8444em"}},[t("span",{class:"pstrut",style:{height:"3.0444em"}}),t("span",{style:{height:"1.0444em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"1.0444em"},[t("line",{x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.2em"}},[t("span")])])])])])])]),s(" | "),t("code",null,"\\bcancel{5}"),s(" | | \\because | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∵")]),t("annotation",{encoding:"application/x-tex"},"\\because")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6922em"}}),t("span",{class:"mrel amsrm"},"∵")])])]),s(" | | | \\begin | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\\\ c & d\\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])]),s(" | "),t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}"),s(" | | \\begingroup | "),t("span",{class:"katex-error",title:"ParseError: KaTeX parse error: Expected '\\endgroup', got '}' at position 14: \\begingroup a}̲"},"\\begingroup a}"),s(" | "),t("code",null,"\\begingroup a}"),s(" | | \\Beta | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"B")]),t("annotation",{encoding:"application/x-tex"},"\\Beta")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord mathrm"},"B")])])]),s(" | | | \\beta | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"β")]),t("annotation",{encoding:"application/x-tex"},"\\beta")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s(" | | | \\beth | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℶ")]),t("annotation",{encoding:"application/x-tex"},"\\beth")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord amsrm"},"ℶ")])])]),s(" | | | \\between | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≬")]),t("annotation",{encoding:"application/x-tex"},"\\between")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0117em","vertical-align":"-0.2558em"}}),t("span",{class:"mrel amsrm"},"≬")])])]),s(" | | | \\bf | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"bold"},"A"),t("mi",{mathvariant:"bold"},"a"),t("mi",{mathvariant:"bold"},"B"),t("mi",{mathvariant:"bold"},"b"),t("mn",{mathvariant:"bold"},"12")]),t("annotation",{encoding:"application/x-tex"},"\\bf AaBb12")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathbf"},"AaBb12")])])])]),s(" | "),t("code",null,"\\bf AaBb12"),s(" | | \\bfseries | "),t("span",{style:{color:"firebrick"}},"Not supported"),s(" | | | \\big | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"1.2em",maxsize:"1.2em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"1.2em",maxsize:"1.2em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\big(\\big)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size1"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size1"},")")])])])]),s(" | "),t("code",null,"\\big(\\big)"),s(" | | \\Big | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"1.8em",maxsize:"1.8em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"1.8em",maxsize:"1.8em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\Big(\\Big)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.8em","vertical-align":"-0.65em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size2"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size2"},")")])])])]),s(" | "),t("code",null,"\\Big(\\Big)"),s(" | | \\bigcap | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋂")]),t("annotation",{encoding:"application/x-tex"},"\\bigcap")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"⋂")])])]),s(" | | | \\bigcirc | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"◯")]),t("annotation",{encoding:"application/x-tex"},"\\bigcirc")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},"◯")])])]),s(" | | | \\bigcup | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋃")]),t("annotation",{encoding:"application/x-tex"},"\\bigcup")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"⋃")])])]),s(" | | | \\bigg | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\bigg(\\bigg)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size3"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size3"},")")])])])]),s(" | "),t("code",null,"\\bigg(\\bigg)"),s(" | | \\Bigg | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\Bigg(\\Bigg)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size4"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size4"},")")])])])]),s(" | "),t("code",null,"\\Bigg(\\Bigg)"),s(" | | \\biggl | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"true",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"(")]),t("annotation",{encoding:"application/x-tex"},"\\biggl(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mopen"},[t("span",{class:"delimsizing size3"},"(")])])])]),s(" | "),t("code",null,"\\biggl("),s(" | | \\Biggl | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"true",stretchy:"true",minsize:"3em",maxsize:"3em"},"(")]),t("annotation",{encoding:"application/x-tex"},"\\Biggl(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mopen"},[t("span",{class:"delimsizing size4"},"(")])])])]),s(" | "),t("code",null,"\\Biggl("),s(" | | \\biggm | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\biggm\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mrel"},[t("span",{class:"delimsizing mult"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.45em"}},[t("span",{class:"pstrut",style:{height:"4.4em"}}),t("span",{style:{width:"0.333em",height:"2.400em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"0.333em",height:"2.400em",viewBox:"0 0 333 2400"},[t("path",{d:`M145 15 v585 v1200 v585 c2.667,10,9.667,15,21,15 c10,0,16.667,-5,20,-15 v-585 v-1200 v-585 c-2.667,-10,-9.667,-15,-21,-15 c-10,0,-16.667,5,-20,15z M188 15 H145 v585 v1200 v585 h43z`})])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])]),s(" | "),t("code",null,"\\biggm\\vert"),s(" | | \\Biggm | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\Biggm\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mrel"},[t("span",{class:"delimsizing mult"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.75em"}},[t("span",{class:"pstrut",style:{height:"5em"}}),t("span",{style:{width:"0.333em",height:"3.000em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"0.333em",height:"3.000em",viewBox:"0 0 333 3000"},[t("path",{d:`M145 15 v585 v1800 v585 c2.667,10,9.667,15,21,15 c10,0,16.667,-5,20,-15 v-585 v-1800 v-585 c-2.667,-10,-9.667,-15,-21,-15 diff --git a/assets/application_markdown-it-katex_support-table.md.52b042b8.lean.js b/assets/application_markdown-it-katex_support-table.md.419e3a5e.lean.js similarity index 99% rename from assets/application_markdown-it-katex_support-table.md.52b042b8.lean.js rename to assets/application_markdown-it-katex_support-table.md.419e3a5e.lean.js index bc167b20..1eb4bc89 100644 --- a/assets/application_markdown-it-katex_support-table.md.52b042b8.lean.js +++ b/assets/application_markdown-it-katex_support-table.md.419e3a5e.lean.js @@ -1,4 +1,4 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as a,c as l,H as m,k as t,a as s,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const sl=JSON.parse('{"title":"KaTeX: Support table","description":"Supported table of KaTeX syntax ordered alphabetically.","frontmatter":{"title":"KaTeX: Support table","description":"Supported table of KaTeX syntax ordered alphabetically."},"headers":[],"relativePath":"application/markdown-it-katex/support-table.md","filePath":"application/markdown-it-katex/support-table.md","lastUpdated":1695377563000}'),p={name:"application/markdown-it-katex/support-table.md"},r=t("h1",{id:"katex-support-table",tabindex:"-1"},[s("KaTeX: Support table "),t("a",{class:"header-anchor",href:"#katex-support-table","aria-label":'Permalink to "KaTeX: Support table"'},"​")],-1),h=c("",2),o=t("table",null,[t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"left"}},"Symbol/Function"),t("th",{style:{"text-align":"left"}},"Rendered"),t("th",{style:{"text-align":"left"}},"Source or Comment")])]),t("tbody",null,[t("tr",null,[t("td",{style:{"text-align":"left"}},"!"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"n"),t("mo",{stretchy:"false"},"!")]),t("annotation",{encoding:"application/x-tex"},"n!")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"n"),t("span",{class:"mclose"},"!")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"n!")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\!"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," ⁣"),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\!b")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"-0.1667em"}}),t("span",{class:"mord mathnormal"},"b")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\!b")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"#"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mi",null,"y"),t("mn",null,"2")])]),t("annotation",{encoding:"application/x-tex"},"\\def\\bar#1{#1^2} \\bar{y}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8141em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},"2")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\def\\bar#1{#1^2} \\bar{y}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\#"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"#")]),t("annotation",{encoding:"application/x-tex"},"\\#")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},"#")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"%"),t("td",{style:{"text-align":"left"}}),t("td",{style:{"text-align":"left"}},[t("code",null,"%this is a comment")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\%"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"%")]),t("annotation",{encoding:"application/x-tex"},"\\%")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8056em","vertical-align":"-0.0556em"}}),t("span",{class:"mord"},"%")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"&"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\cr c & d \\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\&"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"&")]),t("annotation",{encoding:"application/x-tex"},"\\&")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"&")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"'"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mrow"),t("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),t("annotation",{encoding:"application/x-tex"},"'")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.7519em"}}),t("span",{class:"mord"},[t("span"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.7519em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mtight"},"′")])])])])])])])])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\'"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˊ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\'{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˊ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\'{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"("),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"(")]),t("annotation",{encoding:"application/x-tex"},"(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"(")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},")"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},")")]),t("annotation",{encoding:"application/x-tex"},")")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},")")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\(…\\)"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mfrac",null,[t("mi",null,"a"),t("mi",null,"b")])])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\(\\frac a b\\)}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6954em"}},[t("span",{style:{top:"-2.655em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b")])])]),t("span",{style:{top:"-3.23em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),t("span",{style:{top:"-3.394em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.345em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\(\\frac a b\\)}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\ b")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace"}," "),t("span",{class:"mord mathnormal"},"b")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\ b")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},'\\"'),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"¨")])]),t("annotation",{encoding:"application/x-tex"},'\\text{\\"{a}}')])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"¨")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,'\\text{\\"{a}}')])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\$"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"$")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\textdollar}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8056em","vertical-align":"-0.0556em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"$")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\,"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\,\\,{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\,\\,{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\."),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˙")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\.{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1389em"}},[t("span",{class:"mord"},"˙")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\.{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\:"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\:\\:{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\:\\:{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\;"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null,"  "),t("mtext",null,"  "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\;\\;{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[s("a"),t("code",null,"\\;\\;{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"_"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msub",null,[t("mi",null,"x"),t("mi",null,"i")])]),t("annotation",{encoding:"application/x-tex"},"x_i")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"x"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.3117em"}},[t("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mathnormal mtight"},"i")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.15em"}},[t("span")])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"x_i")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\_"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"_")]),t("annotation",{encoding:"application/x-tex"},"\\_")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em","vertical-align":"-0.31em"}}),t("span",{class:"mord",style:{"margin-right":"0.02778em"}},"_")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},[s("\\"),t("code",null,"`")]),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˋ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\`{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˋ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\'{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"<"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"<")]),t("annotation",{encoding:"application/x-tex"},"<")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),t("span",{class:"mrel"},"<")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\="),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˉ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\={a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5678em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5678em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˉ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\={a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},">"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,">")]),t("annotation",{encoding:"application/x-tex"},">")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),t("span",{class:"mrel"},">")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\>"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\>\\>{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\>\\>{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"["),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"[")]),t("annotation",{encoding:"application/x-tex"},"[")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"[")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"]"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"]")]),t("annotation",{encoding:"application/x-tex"},"]")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},"]")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"{"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a")]),t("annotation",{encoding:"application/x-tex"},"{a}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"}"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a")]),t("annotation",{encoding:"application/x-tex"},"{a}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\{"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"{")]),t("annotation",{encoding:"application/x-tex"},"\\{")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"{")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\}"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"}")]),t("annotation",{encoding:"application/x-tex"},"\\}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},"}")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"|"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"∣")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\|"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∥")]),t("annotation",{encoding:"application/x-tex"},"\\Vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"∥")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"~"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"no no no breaks")]),t("annotation",{encoding:"application/x-tex"},"\\text{no~no~no~breaks}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"breaks")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{no~no~no~breaks}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\~"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˜")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\~{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"˜")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\~{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\\\"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\\\ c & d\\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"^"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mi",null,"x"),t("mi",null,"i")])]),t("annotation",{encoding:"application/x-tex"},"x^i")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8247em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"x"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8247em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"x^i")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\^"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˆ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\^{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˆ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\^{a}}")])])])],-1),d=t("h2",{id:"a",tabindex:"-1"},[s("A "),t("a",{class:"header-anchor",href:"#a","aria-label":'Permalink to "A"'},"​")],-1),x=t("table",null,[t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"left"}},"Symbol/Function"),t("th",{style:{"text-align":"left"}},"Rendered"),t("th",{style:{"text-align":"left"}},"Source or Comment")])]),t("tbody",null,[t("tr",null,[t("td",{style:{"text-align":"left"}},"\\AA"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"A"),t("mo",null,"˚")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\AA}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.9468em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.9468em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},"A")]),t("span",{style:{top:"-3.2523em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.375em"}},[t("span",{class:"mord"},"˚")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\AA}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\aa"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˚")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\aa}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},"a")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.375em"}},[t("span",{class:"mord"},"˚")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\aa}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\above"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mfrac",{linethickness:"0.2em"},[t("mi",null,"a"),t("mrow",null,[t("mi",null,"b"),t("mo",null,"+"),t("mn",null,"1")])])]),t("annotation",{encoding:"application/x-tex"},"{a \\above{2pt} b+1}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.4458em","vertical-align":"-0.5944em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8514em"}},[t("span",{style:{top:"-2.4639em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b"),t("span",{class:"mbin mtight"},"+"),t("span",{class:"mord mtight"},"1")])])]),t("span",{style:{top:"-3.15em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"frac-line",style:{"border-bottom-width":"0.2em"}})]),t("span",{style:{top:"-3.55em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5944em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a \\above{2pt} b+1}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\abovewithdelims"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\acute"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mi",null,"e"),t("mo",null,"ˊ")])]),t("annotation",{encoding:"application/x-tex"},"\\acute e")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord mathnormal"},"e")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1944em"}},[t("span",{class:"mord"},"ˊ")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\acute e")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\AE"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"Æ")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\AE}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"Æ")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\AE}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ae"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"æ")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\ae}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"æ")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\ae}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alef"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\alef")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alefsym"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\alefsym")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\aleph"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\aleph")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"},align:""}),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{aligned}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},aligned:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mo",null,"="),t("mi",null,"b"),t("mo",null,"+"),t("mi",null,"c")])])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mi",null,"d"),t("mo",null,"+"),t("mi",null,"e")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mo",null,"="),t("mi",null,"f")])])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{aligned}a&=b+c\\\\d+e&=f\\end{aligned}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mbin"},"+"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord mathnormal"},"e")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord mathnormal"},"b"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mbin"},"+"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord mathnormal"},"c")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{aligned}"),t("br"),s("   "),t("code",null,"a&=b+c \\\\"),t("br"),s("   "),t("code",null,"d+e&=f"),t("br"),t("code",null,"\\end{aligned}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},alignat:""}),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{alignedat}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},alignedat:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.25em",columnalign:"right left right left",columnspacing:"0em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"10")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"x"),t("mo",null,"+")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"3")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"y"),t("mo",null,"="),t("mn",null,"2")])])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"3")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"x"),t("mo",null,"+")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"13")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"y"),t("mo",null,"="),t("mn",null,"4")])])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{alignedat}{2}10&x+&3&y=2\\\\3&x+&13&y=4\\end{alignedat}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"10")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"3")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal"},"x"),t("span",{class:"mord"},"+")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal"},"x"),t("span",{class:"mord"},"+")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"3")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"13")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},"2")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},"4")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{alignedat}{2}"),t("br"),s("   "),t("code",null,"10&x+ &3&y = 2 \\\\"),t("br"),s("   "),t("code",null," 3&x+&13&y = 4"),t("br"),t("code",null,"\\end{alignedat}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\allowbreak"),t("td",{style:{"text-align":"left"}}),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\Alpha"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"A")]),t("annotation",{encoding:"application/x-tex"},"\\Alpha")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord mathrm"},"A")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alpha"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"α")]),t("annotation",{encoding:"application/x-tex"},"\\alpha")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\amalg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⨿")]),t("annotation",{encoding:"application/x-tex"},"\\amalg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord"},"⨿")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\And"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"&")]),t("annotation",{encoding:"application/x-tex"},"\\And")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"&")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\and"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[t("a",{href:"https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax",target:"_blank",rel:"noreferrer"},"Deprecated")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ang"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[t("a",{href:"https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax",target:"_blank",rel:"noreferrer"},"Deprecated")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\angl"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\angle"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∠")]),t("annotation",{encoding:"application/x-tex"},"\\angle")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6922em"}}),t("span",{class:"mord"},"∠")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\approx"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≈")]),t("annotation",{encoding:"application/x-tex"},"\\approx")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4831em"}}),t("span",{class:"mrel"},"≈")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\approxeq"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≊")]),t("annotation",{encoding:"application/x-tex"},"\\approxeq")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6633em","vertical-align":"-0.0817em"}}),t("span",{class:"mrel amsrm"},"≊")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arccos"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arccos"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arccos")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mop"},"arccos")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arcctg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arcctg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arcctg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("arcct"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arcsin"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arcsin"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arcsin")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mop"},"arcsin")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arctan"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arctan"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arctan")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6151em"}}),t("span",{class:"mop"},"arctan")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arctg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arctg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arctg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("arct"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("ar"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\argmax"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"arg max"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\argmax")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[t("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"arg"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord mathrm"},"max")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\argmin"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"arg min"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\argmin")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8623em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[t("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"arg"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord mathrm"},"min")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"},array:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{array}{cc}a&b\\\\c&d\\end{array}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{array}{cc}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\array"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arraystretch"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.66em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\def\\arraystretch{1.5}\\begin{array}{cc}a&b\\\\c&d\\end{array}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3.6em","vertical-align":"-1.55em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"2.05em"}},[t("span",{style:{top:"-4.05em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.25em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.55em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"2.05em"}},[t("span",{style:{top:"-4.05em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.25em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.55em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\def\\arraystretch{1.5}"),t("br"),t("code",null,"\\begin{array}{cc}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\Arrowvert"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arrowvert"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ast"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∗")]),t("annotation",{encoding:"application/x-tex"},"\\ast")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4653em"}}),t("span",{class:"mord"},"∗")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\asymp"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≍")]),t("annotation",{encoding:"application/x-tex"},"\\asymp")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4637em"}}),t("span",{class:"mrel"},"≍")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\atop"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mfrac",{linethickness:"0px"},[t("mi",null,"a"),t("mi",null,"b")])]),t("annotation",{encoding:"application/x-tex"},"{a \\atop b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0904em","vertical-align":"-0.345em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.7454em"}},[t("span",{style:{top:"-2.355em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b")])])]),t("span",{style:{top:"-3.144em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.345em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a \\atop b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\atopwithdelims"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})])])],-1),g=t("h2",{id:"b",tabindex:"-1"},[s("B "),t("a",{class:"header-anchor",href:"#b","aria-label":'Permalink to "B"'},"​")],-1),u=t("p",null,[s("| Symbol/Function | Rendered | Source or Comment | | :------------------ | :-------------------------------------------------- | :------------------------------------------------------------------------------------------------ | ------ | | \\backepsilon | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∍")]),t("annotation",{encoding:"application/x-tex"},"\\backepsilon")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mrel amsrm"},"∍")])])]),s(" | | | \\backprime | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"‵")]),t("annotation",{encoding:"application/x-tex"},"\\backprime")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5499em"}}),t("span",{class:"mord amsrm"},"‵")])])]),s(" | | | \\backsim | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∽")]),t("annotation",{encoding:"application/x-tex"},"\\backsim")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.3779em"}}),t("span",{class:"mrel amsrm"},"∽")])])]),s(" | | | \\backsimeq | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋍")]),t("annotation",{encoding:"application/x-tex"},"\\backsimeq")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.464em"}}),t("span",{class:"mrel amsrm"},"⋍")])])]),s(" | | | \\backslash | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"\\")]),t("annotation",{encoding:"application/x-tex"},"\\backslash")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"\\")])])]),s(" | | | \\bar | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mi",null,"y"),t("mo",null,"ˉ")])]),t("annotation",{encoding:"application/x-tex"},"\\bar{y}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.7622em","vertical-align":"-0.1944em"}}),t("span",{class:"mord accent"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5678em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1944em"}},[t("span",{class:"mord"},"ˉ")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.1944em"}},[t("span")])])])])])])]),s(" | "),t("code",null,"\\bar{y}"),s(" | | \\barwedge | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⊼")]),t("annotation",{encoding:"application/x-tex"},"\\barwedge")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8867em","vertical-align":"-0.1944em"}}),t("span",{class:"mord amsrm"},"⊼")])])]),s(" | | | \\Bbb | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"double-struck"},"A"),t("mi",{mathvariant:"double-struck"},"B"),t("mi",{mathvariant:"double-struck"},"C")]),t("annotation",{encoding:"application/x-tex"},"\\Bbb{ABC}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathbb"},"ABC")])])])]),s(" | "),t("code",null,"\\Bbb{ABC}"),t("br"),s("KaTeX supports A-Z & k | | \\Bbbk | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"double-struck"},"k")]),t("annotation",{encoding:"application/x-tex"},"\\Bbbk")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord mathbb"},"k")])])]),s(" | | | \\bbox | "),t("span",{style:{color:"firebrick"}},"Not supported"),s(" | | | \\bcancel | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("menclose",{notation:"downdiagonalstrike"},[t("mn",null,"5")])]),t("annotation",{encoding:"application/x-tex"},"\\bcancel{5}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6444em"}}),t("span",{class:"mord"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8444em"}},[t("span",{style:{top:"-3.0444em"}},[t("span",{class:"pstrut",style:{height:"3.0444em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"5")])]),t("span",{class:"svg-align",style:{top:"-2.8444em"}},[t("span",{class:"pstrut",style:{height:"3.0444em"}}),t("span",{style:{height:"1.0444em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"1.0444em"},[t("line",{x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.2em"}},[t("span")])])])])])])]),s(" | "),t("code",null,"\\bcancel{5}"),s(" | | \\because | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∵")]),t("annotation",{encoding:"application/x-tex"},"\\because")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6922em"}}),t("span",{class:"mrel amsrm"},"∵")])])]),s(" | | | \\begin | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\\\ c & d\\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])]),s(" | "),t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}"),s(" | | \\begingroup | "),t("span",{class:"katex-error",title:"ParseError: KaTeX parse error: Expected '\\endgroup', got '}' at position 14: \\begingroup a}̲"},"\\begingroup a}"),s(" | "),t("code",null,"\\begingroup a}"),s(" | | \\Beta | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"B")]),t("annotation",{encoding:"application/x-tex"},"\\Beta")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord mathrm"},"B")])])]),s(" | | | \\beta | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"β")]),t("annotation",{encoding:"application/x-tex"},"\\beta")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s(" | | | \\beth | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℶ")]),t("annotation",{encoding:"application/x-tex"},"\\beth")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord amsrm"},"ℶ")])])]),s(" | | | \\between | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≬")]),t("annotation",{encoding:"application/x-tex"},"\\between")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0117em","vertical-align":"-0.2558em"}}),t("span",{class:"mrel amsrm"},"≬")])])]),s(" | | | \\bf | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"bold"},"A"),t("mi",{mathvariant:"bold"},"a"),t("mi",{mathvariant:"bold"},"B"),t("mi",{mathvariant:"bold"},"b"),t("mn",{mathvariant:"bold"},"12")]),t("annotation",{encoding:"application/x-tex"},"\\bf AaBb12")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathbf"},"AaBb12")])])])]),s(" | "),t("code",null,"\\bf AaBb12"),s(" | | \\bfseries | "),t("span",{style:{color:"firebrick"}},"Not supported"),s(" | | | \\big | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"1.2em",maxsize:"1.2em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"1.2em",maxsize:"1.2em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\big(\\big)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size1"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size1"},")")])])])]),s(" | "),t("code",null,"\\big(\\big)"),s(" | | \\Big | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"1.8em",maxsize:"1.8em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"1.8em",maxsize:"1.8em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\Big(\\Big)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.8em","vertical-align":"-0.65em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size2"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size2"},")")])])])]),s(" | "),t("code",null,"\\Big(\\Big)"),s(" | | \\bigcap | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋂")]),t("annotation",{encoding:"application/x-tex"},"\\bigcap")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"⋂")])])]),s(" | | | \\bigcirc | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"◯")]),t("annotation",{encoding:"application/x-tex"},"\\bigcirc")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},"◯")])])]),s(" | | | \\bigcup | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋃")]),t("annotation",{encoding:"application/x-tex"},"\\bigcup")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"⋃")])])]),s(" | | | \\bigg | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\bigg(\\bigg)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size3"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size3"},")")])])])]),s(" | "),t("code",null,"\\bigg(\\bigg)"),s(" | | \\Bigg | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\Bigg(\\Bigg)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size4"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size4"},")")])])])]),s(" | "),t("code",null,"\\Bigg(\\Bigg)"),s(" | | \\biggl | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"true",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"(")]),t("annotation",{encoding:"application/x-tex"},"\\biggl(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mopen"},[t("span",{class:"delimsizing size3"},"(")])])])]),s(" | "),t("code",null,"\\biggl("),s(" | | \\Biggl | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"true",stretchy:"true",minsize:"3em",maxsize:"3em"},"(")]),t("annotation",{encoding:"application/x-tex"},"\\Biggl(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mopen"},[t("span",{class:"delimsizing size4"},"(")])])])]),s(" | "),t("code",null,"\\Biggl("),s(" | | \\biggm | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\biggm\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mrel"},[t("span",{class:"delimsizing mult"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.45em"}},[t("span",{class:"pstrut",style:{height:"4.4em"}}),t("span",{style:{width:"0.333em",height:"2.400em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"0.333em",height:"2.400em",viewBox:"0 0 333 2400"},[t("path",{d:`M145 15 v585 v1200 v585 c2.667,10,9.667,15,21,15 +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as a,c as l,H as m,k as t,a as s,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const sl=JSON.parse('{"title":"KaTeX: Support table","description":"Supported table of KaTeX syntax ordered alphabetically.","frontmatter":{"title":"KaTeX: Support table","description":"Supported table of KaTeX syntax ordered alphabetically."},"headers":[],"relativePath":"application/markdown-it-katex/support-table.md","filePath":"application/markdown-it-katex/support-table.md","lastUpdated":1699051935000}'),p={name:"application/markdown-it-katex/support-table.md"},r=t("h1",{id:"katex-support-table",tabindex:"-1"},[s("KaTeX: Support table "),t("a",{class:"header-anchor",href:"#katex-support-table","aria-label":'Permalink to "KaTeX: Support table"'},"​")],-1),h=c("",2),o=t("table",null,[t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"left"}},"Symbol/Function"),t("th",{style:{"text-align":"left"}},"Rendered"),t("th",{style:{"text-align":"left"}},"Source or Comment")])]),t("tbody",null,[t("tr",null,[t("td",{style:{"text-align":"left"}},"!"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"n"),t("mo",{stretchy:"false"},"!")]),t("annotation",{encoding:"application/x-tex"},"n!")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"n"),t("span",{class:"mclose"},"!")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"n!")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\!"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," ⁣"),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\!b")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"-0.1667em"}}),t("span",{class:"mord mathnormal"},"b")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\!b")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"#"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mi",null,"y"),t("mn",null,"2")])]),t("annotation",{encoding:"application/x-tex"},"\\def\\bar#1{#1^2} \\bar{y}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0085em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8141em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},"2")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\def\\bar#1{#1^2} \\bar{y}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\#"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"#")]),t("annotation",{encoding:"application/x-tex"},"\\#")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},"#")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"%"),t("td",{style:{"text-align":"left"}}),t("td",{style:{"text-align":"left"}},[t("code",null,"%this is a comment")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\%"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"%")]),t("annotation",{encoding:"application/x-tex"},"\\%")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8056em","vertical-align":"-0.0556em"}}),t("span",{class:"mord"},"%")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"&"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\cr c & d \\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\&"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"&")]),t("annotation",{encoding:"application/x-tex"},"\\&")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"&")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"'"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mrow"),t("mo",{mathvariant:"normal",lspace:"0em",rspace:"0em"},"′")])]),t("annotation",{encoding:"application/x-tex"},"'")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.7519em"}}),t("span",{class:"mord"},[t("span"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.7519em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mtight"},"′")])])])])])])])])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\'"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˊ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\'{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˊ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\'{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"("),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"(")]),t("annotation",{encoding:"application/x-tex"},"(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"(")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},")"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},")")]),t("annotation",{encoding:"application/x-tex"},")")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},")")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\(…\\)"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mfrac",null,[t("mi",null,"a"),t("mi",null,"b")])])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\(\\frac a b\\)}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0404em","vertical-align":"-0.345em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6954em"}},[t("span",{style:{top:"-2.655em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b")])])]),t("span",{style:{top:"-3.23em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"frac-line",style:{"border-bottom-width":"0.04em"}})]),t("span",{style:{top:"-3.394em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.345em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\(\\frac a b\\)}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\ b")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace"}," "),t("span",{class:"mord mathnormal"},"b")])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\ b")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},'\\"'),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"¨")])]),t("annotation",{encoding:"application/x-tex"},'\\text{\\"{a}}')])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"¨")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,'\\text{\\"{a}}')])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\$"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"$")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\textdollar}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8056em","vertical-align":"-0.0556em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"$")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\,"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\,\\,{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\,\\,{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\."),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˙")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\.{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1389em"}},[t("span",{class:"mord"},"˙")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\.{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\:"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\:\\:{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\:\\:{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\;"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null,"  "),t("mtext",null,"  "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\;\\;{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[s("a"),t("code",null,"\\;\\;{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"_"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msub",null,[t("mi",null,"x"),t("mi",null,"i")])]),t("annotation",{encoding:"application/x-tex"},"x_i")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"x"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.3117em"}},[t("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mathnormal mtight"},"i")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.15em"}},[t("span")])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"x_i")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\_"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"_")]),t("annotation",{encoding:"application/x-tex"},"\\_")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em","vertical-align":"-0.31em"}}),t("span",{class:"mord",style:{"margin-right":"0.02778em"}},"_")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},[s("\\"),t("code",null,"`")]),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˋ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\`{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˋ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\'{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"<"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"<")]),t("annotation",{encoding:"application/x-tex"},"<")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),t("span",{class:"mrel"},"<")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\="),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˉ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\={a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5678em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5678em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˉ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\={a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},">"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,">")]),t("annotation",{encoding:"application/x-tex"},">")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5782em","vertical-align":"-0.0391em"}}),t("span",{class:"mrel"},">")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\>"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a"),t("mtext",null," "),t("mtext",null," "),t("mi",null,"b")]),t("annotation",{encoding:"application/x-tex"},"a\\>\\>{b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord mathnormal"},"a"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"a\\>\\>{b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"["),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"[")]),t("annotation",{encoding:"application/x-tex"},"[")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"[")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"]"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"]")]),t("annotation",{encoding:"application/x-tex"},"]")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},"]")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"{"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a")]),t("annotation",{encoding:"application/x-tex"},"{a}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"}"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"a")]),t("annotation",{encoding:"application/x-tex"},"{a}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\{"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"{")]),t("annotation",{encoding:"application/x-tex"},"\\{")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mopen"},"{")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\}"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{stretchy:"false"},"}")]),t("annotation",{encoding:"application/x-tex"},"\\}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mclose"},"}")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"|"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"∣")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\|"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∥")]),t("annotation",{encoding:"application/x-tex"},"\\Vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"∥")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"~"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"no no no breaks")]),t("annotation",{encoding:"application/x-tex"},"\\text{no~no~no~breaks}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"no"),t("span",{class:"mord nobreak"}," "),t("span",{class:"mord"},"breaks")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{no~no~no~breaks}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\~"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˜")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\~{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6679em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"˜")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\~{a}}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\\\"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\\\ c & d\\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"^"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("msup",null,[t("mi",null,"x"),t("mi",null,"i")])]),t("annotation",{encoding:"application/x-tex"},"x^i")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8247em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"x"),t("span",{class:"msupsub"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8247em"}},[t("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mathnormal mtight"},"i")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"x^i")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\^"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"ˆ")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\^{a}}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"a")])]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.25em"}},[t("span",{class:"mord"},"ˆ")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\\\^{a}}")])])])],-1),d=t("h2",{id:"a",tabindex:"-1"},[s("A "),t("a",{class:"header-anchor",href:"#a","aria-label":'Permalink to "A"'},"​")],-1),x=t("table",null,[t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"left"}},"Symbol/Function"),t("th",{style:{"text-align":"left"}},"Rendered"),t("th",{style:{"text-align":"left"}},"Source or Comment")])]),t("tbody",null,[t("tr",null,[t("td",{style:{"text-align":"left"}},"\\AA"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"A"),t("mo",null,"˚")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\AA}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.9468em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.9468em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},"A")]),t("span",{style:{top:"-3.2523em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.375em"}},[t("span",{class:"mord"},"˚")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\AA}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\aa"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mtext",null,"a"),t("mo",null,"˚")])]),t("annotation",{encoding:"application/x-tex"},"\\text{\\aa}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord text"},[t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},"a")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.375em"}},[t("span",{class:"mord"},"˚")])])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\aa}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\above"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mfrac",{linethickness:"0.2em"},[t("mi",null,"a"),t("mrow",null,[t("mi",null,"b"),t("mo",null,"+"),t("mn",null,"1")])])]),t("annotation",{encoding:"application/x-tex"},"{a \\above{2pt} b+1}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.4458em","vertical-align":"-0.5944em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8514em"}},[t("span",{style:{top:"-2.4639em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b"),t("span",{class:"mbin mtight"},"+"),t("span",{class:"mord mtight"},"1")])])]),t("span",{style:{top:"-3.15em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"frac-line",style:{"border-bottom-width":"0.2em"}})]),t("span",{style:{top:"-3.55em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5944em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a \\above{2pt} b+1}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\abovewithdelims"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\acute"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mi",null,"e"),t("mo",null,"ˊ")])]),t("annotation",{encoding:"application/x-tex"},"\\acute e")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord accent"},[t("span",{class:"vlist-t"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.6944em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord mathnormal"},"e")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1944em"}},[t("span",{class:"mord"},"ˊ")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\acute e")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\AE"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"Æ")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\AE}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"Æ")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\AE}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ae"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mtext",null,"æ")]),t("annotation",{encoding:"application/x-tex"},"\\text{\\ae}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord text"},[t("span",{class:"mord"},"æ")])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\text{\\ae}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alef"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\alef")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alefsym"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\alefsym")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\aleph"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℵ")]),t("annotation",{encoding:"application/x-tex"},"\\aleph")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"ℵ")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"},align:""}),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{aligned}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},aligned:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mo",null,"="),t("mi",null,"b"),t("mo",null,"+"),t("mi",null,"c")])])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mi",null,"d"),t("mo",null,"+"),t("mi",null,"e")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mo",null,"="),t("mi",null,"f")])])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{aligned}a&=b+c\\\\d+e&=f\\end{aligned}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mbin"},"+"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord mathnormal"},"e")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord mathnormal"},"b"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mbin"},"+"),t("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),t("span",{class:"mord mathnormal"},"c")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.10764em"}},"f")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{aligned}"),t("br"),s("   "),t("code",null,"a&=b+c \\\\"),t("br"),s("   "),t("code",null,"d+e&=f"),t("br"),t("code",null,"\\end{aligned}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},alignat:""}),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{alignedat}")])]),t("tr",null,[t("td",{style:{"text-align":"left"},alignedat:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.25em",columnalign:"right left right left",columnspacing:"0em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"10")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"x"),t("mo",null,"+")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"3")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"y"),t("mo",null,"="),t("mn",null,"2")])])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"3")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"x"),t("mo",null,"+")])])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mn",null,"13")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"true"},[t("mrow",null,[t("mrow"),t("mi",null,"y"),t("mo",null,"="),t("mn",null,"4")])])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{alignedat}{2}10&x+&3&y=2\\\\3&x+&13&y=4\\end{alignedat}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"10")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"3")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal"},"x"),t("span",{class:"mord"},"+")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal"},"x"),t("span",{class:"mord"},"+")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-r"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"3")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"13")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])]),t("span",{class:"col-align-l"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.91em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},"2")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord"}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mrel"},"="),t("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),t("span",{class:"mord"},"4")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.25em"}},[t("span")])])])])])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{alignedat}{2}"),t("br"),s("   "),t("code",null,"10&x+ &3&y = 2 \\\\"),t("br"),s("   "),t("code",null," 3&x+&13&y = 4"),t("br"),t("code",null,"\\end{alignedat}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\allowbreak"),t("td",{style:{"text-align":"left"}}),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\Alpha"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"A")]),t("annotation",{encoding:"application/x-tex"},"\\Alpha")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord mathrm"},"A")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\alpha"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"α")]),t("annotation",{encoding:"application/x-tex"},"\\alpha")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.0037em"}},"α")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\amalg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⨿")]),t("annotation",{encoding:"application/x-tex"},"\\amalg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord"},"⨿")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\And"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"&")]),t("annotation",{encoding:"application/x-tex"},"\\And")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},"&")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\and"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[t("a",{href:"https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax",target:"_blank",rel:"noreferrer"},"Deprecated")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ang"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[t("a",{href:"https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax",target:"_blank",rel:"noreferrer"},"Deprecated")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\angl"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\angle"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"∠")]),t("annotation",{encoding:"application/x-tex"},"\\angle")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6922em"}}),t("span",{class:"mord"},"∠")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\approx"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≈")]),t("annotation",{encoding:"application/x-tex"},"\\approx")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4831em"}}),t("span",{class:"mrel"},"≈")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\approxeq"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≊")]),t("annotation",{encoding:"application/x-tex"},"\\approxeq")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6633em","vertical-align":"-0.0817em"}}),t("span",{class:"mrel amsrm"},"≊")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arccos"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arccos"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arccos")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mop"},"arccos")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arcctg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arcctg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arcctg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("arcct"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arcsin"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arcsin"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arcsin")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6679em"}}),t("span",{class:"mop"},"arcsin")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arctan"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arctan"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arctan")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6151em"}}),t("span",{class:"mop"},"arctan")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arctg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arctg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arctg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8095em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("arct"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arg"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"arg"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\arg")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[s("ar"),t("span",{style:{"margin-right":"0.01389em"}},"g")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\argmax"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"arg max"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\argmax")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[t("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"arg"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord mathrm"},"max")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\argmin"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"arg min"),t("mo",null,"⁡")]),t("annotation",{encoding:"application/x-tex"},"\\argmin")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8623em","vertical-align":"-0.1944em"}}),t("span",{class:"mop"},[t("span",{class:"mord mathrm",style:{"margin-right":"0.01389em"}},"arg"),t("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),t("span",{class:"mord mathrm"},"min")])])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"},array:""}),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{array}{cc}a&b\\\\c&d\\end{array}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\begin{array}{cc}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\array"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}},[s("see "),t("code",null,"{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arraystretch"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.66em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\def\\arraystretch{1.5}\\begin{array}{cc}a&b\\\\c&d\\end{array}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3.6em","vertical-align":"-1.55em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"2.05em"}},[t("span",{style:{top:"-4.05em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.25em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.55em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"2.05em"}},[t("span",{style:{top:"-4.05em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.25em"}},[t("span",{class:"pstrut",style:{height:"3.26em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.55em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"\\def\\arraystretch{1.5}"),t("br"),t("code",null,"\\begin{array}{cc}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{array}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\Arrowvert"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\arrowvert"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\ast"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∗")]),t("annotation",{encoding:"application/x-tex"},"\\ast")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4653em"}}),t("span",{class:"mord"},"∗")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\asymp"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≍")]),t("annotation",{encoding:"application/x-tex"},"\\asymp")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4637em"}}),t("span",{class:"mrel"},"≍")])])])]),t("td",{style:{"text-align":"left"}})]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\atop"),t("td",{style:{"text-align":"left"}},[t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mfrac",{linethickness:"0px"},[t("mi",null,"a"),t("mi",null,"b")])]),t("annotation",{encoding:"application/x-tex"},"{a \\atop b}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0904em","vertical-align":"-0.345em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},[t("span",{class:"mopen nulldelimiter"}),t("span",{class:"mfrac"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.7454em"}},[t("span",{style:{top:"-2.355em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"b")])])]),t("span",{style:{top:"-3.144em"}},[t("span",{class:"pstrut",style:{height:"2.7em"}}),t("span",{class:"sizing reset-size6 size3 mtight"},[t("span",{class:"mord mtight"},[t("span",{class:"mord mathnormal mtight"},"a")])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.345em"}},[t("span")])])])]),t("span",{class:"mclose nulldelimiter"})])])])])])]),t("td",{style:{"text-align":"left"}},[t("code",null,"{a \\atop b}")])]),t("tr",null,[t("td",{style:{"text-align":"left"}},"\\atopwithdelims"),t("td",{style:{"text-align":"left"}},[t("span",{style:{color:"firebrick"}},"Not supported")]),t("td",{style:{"text-align":"left"}})])])],-1),g=t("h2",{id:"b",tabindex:"-1"},[s("B "),t("a",{class:"header-anchor",href:"#b","aria-label":'Permalink to "B"'},"​")],-1),u=t("p",null,[s("| Symbol/Function | Rendered | Source or Comment | | :------------------ | :-------------------------------------------------- | :------------------------------------------------------------------------------------------------ | ------ | | \\backepsilon | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∍")]),t("annotation",{encoding:"application/x-tex"},"\\backepsilon")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.4306em"}}),t("span",{class:"mrel amsrm"},"∍")])])]),s(" | | | \\backprime | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"‵")]),t("annotation",{encoding:"application/x-tex"},"\\backprime")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.5499em"}}),t("span",{class:"mord amsrm"},"‵")])])]),s(" | | | \\backsim | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∽")]),t("annotation",{encoding:"application/x-tex"},"\\backsim")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.3779em"}}),t("span",{class:"mrel amsrm"},"∽")])])]),s(" | | | \\backsimeq | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋍")]),t("annotation",{encoding:"application/x-tex"},"\\backsimeq")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.464em"}}),t("span",{class:"mrel amsrm"},"⋍")])])]),s(" | | | \\backslash | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"\\")]),t("annotation",{encoding:"application/x-tex"},"\\backslash")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mord"},"\\")])])]),s(" | | | \\bar | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mover",{accent:"true"},[t("mi",null,"y"),t("mo",null,"ˉ")])]),t("annotation",{encoding:"application/x-tex"},"\\bar{y}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.7622em","vertical-align":"-0.1944em"}}),t("span",{class:"mord accent"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.5678em"}},[t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")]),t("span",{style:{top:"-3em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"accent-body",style:{left:"-0.1944em"}},[t("span",{class:"mord"},"ˉ")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.1944em"}},[t("span")])])])])])])]),s(" | "),t("code",null,"\\bar{y}"),s(" | | \\barwedge | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⊼")]),t("annotation",{encoding:"application/x-tex"},"\\barwedge")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8867em","vertical-align":"-0.1944em"}}),t("span",{class:"mord amsrm"},"⊼")])])]),s(" | | | \\Bbb | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"double-struck"},"A"),t("mi",{mathvariant:"double-struck"},"B"),t("mi",{mathvariant:"double-struck"},"C")]),t("annotation",{encoding:"application/x-tex"},"\\Bbb{ABC}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathbb"},"ABC")])])])]),s(" | "),t("code",null,"\\Bbb{ABC}"),t("br"),s("KaTeX supports A-Z & k | | \\Bbbk | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"double-struck"},"k")]),t("annotation",{encoding:"application/x-tex"},"\\Bbbk")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord mathbb"},"k")])])]),s(" | | | \\bbox | "),t("span",{style:{color:"firebrick"}},"Not supported"),s(" | | | \\bcancel | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("menclose",{notation:"downdiagonalstrike"},[t("mn",null,"5")])]),t("annotation",{encoding:"application/x-tex"},"\\bcancel{5}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6444em"}}),t("span",{class:"mord"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.8444em"}},[t("span",{style:{top:"-3.0444em"}},[t("span",{class:"pstrut",style:{height:"3.0444em"}}),t("span",{class:"mord"},[t("span",{class:"mord"},"5")])]),t("span",{class:"svg-align",style:{top:"-2.8444em"}},[t("span",{class:"pstrut",style:{height:"3.0444em"}}),t("span",{style:{height:"1.0444em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"1.0444em"},[t("line",{x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.2em"}},[t("span")])])])])])])]),s(" | "),t("code",null,"\\bcancel{5}"),s(" | | \\because | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"∵")]),t("annotation",{encoding:"application/x-tex"},"\\because")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6922em"}}),t("span",{class:"mrel amsrm"},"∵")])])]),s(" | | | \\begin | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mtable",{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em"},[t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"a")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"b")])])]),t("mtr",null,[t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"c")])]),t("mtd",null,[t("mstyle",{scriptlevel:"0",displaystyle:"false"},[t("mi",null,"d")])])])]),t("annotation",{encoding:"application/x-tex"},"\\begin{matrix} a & b\\\\ c & d\\end{matrix}")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"mtable"},[t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"a")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"c")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])]),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"arraycolsep",style:{width:"0.5em"}}),t("span",{class:"col-align-c"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.61em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"b")])]),t("span",{style:{top:"-2.41em"}},[t("span",{class:"pstrut",style:{height:"3em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathnormal"},"d")])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])])]),s(" | "),t("code",null,"\\begin{matrix}"),t("br"),s("   "),t("code",null,"a & b \\\\"),t("br"),s("   "),t("code",null,"c & d"),t("br"),t("code",null,"\\end{matrix}"),s(" | | \\begingroup | "),t("span",{class:"katex-error",title:"ParseError: KaTeX parse error: Expected '\\endgroup', got '}' at position 14: \\begingroup a}̲"},"\\begingroup a}"),s(" | "),t("code",null,"\\begingroup a}"),s(" | | \\Beta | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"B")]),t("annotation",{encoding:"application/x-tex"},"\\Beta")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6833em"}}),t("span",{class:"mord mathrm"},"B")])])]),s(" | | | \\beta | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",null,"β")]),t("annotation",{encoding:"application/x-tex"},"\\beta")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord mathnormal",style:{"margin-right":"0.05278em"}},"β")])])]),s(" | | | \\beth | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"normal"},"ℶ")]),t("annotation",{encoding:"application/x-tex"},"\\beth")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6889em"}}),t("span",{class:"mord amsrm"},"ℶ")])])]),s(" | | | \\between | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"≬")]),t("annotation",{encoding:"application/x-tex"},"\\between")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.0117em","vertical-align":"-0.2558em"}}),t("span",{class:"mrel amsrm"},"≬")])])]),s(" | | | \\bf | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mi",{mathvariant:"bold"},"A"),t("mi",{mathvariant:"bold"},"a"),t("mi",{mathvariant:"bold"},"B"),t("mi",{mathvariant:"bold"},"b"),t("mn",{mathvariant:"bold"},"12")]),t("annotation",{encoding:"application/x-tex"},"\\bf AaBb12")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.6944em"}}),t("span",{class:"mord"},[t("span",{class:"mord mathbf"},"AaBb12")])])])]),s(" | "),t("code",null,"\\bf AaBb12"),s(" | | \\bfseries | "),t("span",{style:{color:"firebrick"}},"Not supported"),s(" | | | \\big | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"1.2em",maxsize:"1.2em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"1.2em",maxsize:"1.2em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\big(\\big)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.2em","vertical-align":"-0.35em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size1"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size1"},")")])])])]),s(" | "),t("code",null,"\\big(\\big)"),s(" | | \\Big | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"1.8em",maxsize:"1.8em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"1.8em",maxsize:"1.8em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\Big(\\Big)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1.8em","vertical-align":"-0.65em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size2"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size2"},")")])])])]),s(" | "),t("code",null,"\\Big(\\Big)"),s(" | | \\bigcap | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋂")]),t("annotation",{encoding:"application/x-tex"},"\\bigcap")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"⋂")])])]),s(" | | | \\bigcirc | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"◯")]),t("annotation",{encoding:"application/x-tex"},"\\bigcirc")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),t("span",{class:"mord"},"◯")])])]),s(" | | | \\bigcup | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",null,"⋃")]),t("annotation",{encoding:"application/x-tex"},"\\bigcup")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),t("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"⋃")])])]),s(" | | | \\bigg | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\bigg(\\bigg)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size3"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size3"},")")])])])]),s(" | "),t("code",null,"\\bigg(\\bigg)"),s(" | | \\Bigg | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},"("),t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},")")]),t("annotation",{encoding:"application/x-tex"},"\\Bigg(\\Bigg)")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mord"},[t("span",{class:"delimsizing size4"},"(")]),t("span",{class:"mord"},[t("span",{class:"delimsizing size4"},")")])])])]),s(" | "),t("code",null,"\\Bigg(\\Bigg)"),s(" | | \\biggl | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"true",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"(")]),t("annotation",{encoding:"application/x-tex"},"\\biggl(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mopen"},[t("span",{class:"delimsizing size3"},"(")])])])]),s(" | "),t("code",null,"\\biggl("),s(" | | \\Biggl | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"true",stretchy:"true",minsize:"3em",maxsize:"3em"},"(")]),t("annotation",{encoding:"application/x-tex"},"\\Biggl(")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mopen"},[t("span",{class:"delimsizing size4"},"(")])])])]),s(" | "),t("code",null,"\\Biggl("),s(" | | \\biggm | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"2.4em",maxsize:"2.4em"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\biggm\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),t("span",{class:"mrel"},[t("span",{class:"delimsizing mult"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.45em"}},[t("span",{style:{top:"-3.45em"}},[t("span",{class:"pstrut",style:{height:"4.4em"}}),t("span",{style:{width:"0.333em",height:"2.400em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"0.333em",height:"2.400em",viewBox:"0 0 333 2400"},[t("path",{d:`M145 15 v585 v1200 v585 c2.667,10,9.667,15,21,15 c10,0,16.667,-5,20,-15 v-585 v-1200 v-585 c-2.667,-10,-9.667,-15,-21,-15 c-10,0,-16.667,5,-20,15z M188 15 H145 v585 v1200 v585 h43z`})])])])]),t("span",{class:"vlist-s"},"​")]),t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"0.95em"}},[t("span")])])])])])])])]),s(" | "),t("code",null,"\\biggm\\vert"),s(" | | \\Biggm | "),t("span",{class:"katex"},[t("span",{class:"katex-mathml"},[t("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[t("semantics",null,[t("mrow",null,[t("mo",{fence:"false",stretchy:"true",minsize:"3em",maxsize:"3em"},"∣")]),t("annotation",{encoding:"application/x-tex"},"\\Biggm\\vert")])])]),t("span",{class:"katex-html","aria-hidden":"true"},[t("span",{class:"base"},[t("span",{class:"strut",style:{height:"3em","vertical-align":"-1.25em"}}),t("span",{class:"mrel"},[t("span",{class:"delimsizing mult"},[t("span",{class:"vlist-t vlist-t2"},[t("span",{class:"vlist-r"},[t("span",{class:"vlist",style:{height:"1.75em"}},[t("span",{style:{top:"-3.75em"}},[t("span",{class:"pstrut",style:{height:"5em"}}),t("span",{style:{width:"0.333em",height:"3.000em"}},[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"0.333em",height:"3.000em",viewBox:"0 0 333 3000"},[t("path",{d:`M145 15 v585 v1800 v585 c2.667,10,9.667,15,21,15 c10,0,16.667,-5,20,-15 v-585 v-1800 v-585 c-2.667,-10,-9.667,-15,-21,-15 diff --git a/assets/application_markdown-it-katex_tips.md.4fa4c33c.js b/assets/application_markdown-it-katex_tips.md.4fa4c33c.js deleted file mode 100644 index 5cedceff..00000000 --- a/assets/application_markdown-it-katex_tips.md.4fa4c33c.js +++ /dev/null @@ -1,97 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as o,H as p,k as s,a as t,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const i="/assets/2023-03-22-17-04-25.d7c4c068.png",c="/assets/2023-03-22-20-29-28.39883b7f.png",d="/assets/2023-05-22-10-14-11.2c283da4.png",y="/assets/2023-05-22-10-27-47.c0db4fe7.png",T=JSON.parse('{"title":"Tips to Use markdown-it-katex","description":"Extra tips on using markdown-it-katex for the best experiences.","frontmatter":{"title":"Tips to Use markdown-it-katex","description":"Extra tips on using markdown-it-katex for the best experiences."},"headers":[],"relativePath":"application/markdown-it-katex/tips.md","filePath":"application/markdown-it-katex/tips.md","lastUpdated":1695377563000}'),h={name:"application/markdown-it-katex/tips.md"},u=s("h1",{id:"tips-hacks",tabindex:"-1"},[t("Tips & Hacks "),s("a",{class:"header-anchor",href:"#tips-hacks","aria-label":'Permalink to "Tips & Hacks"'},"​")],-1),m=r('

    1: Responsive KaTeX Styling

    1.1: Issue background

    KaTeX works out of the box on large screen devices such as laptops and desktop computers. But as KaTeX's built-in does not support responsiveness on it's default stylings, hence KaTeX equations might overflow out of the default width of the default application containers on small-screened mobile devices as you can see in the following image in the dev tool of chrome, when the dimension of the webpage is set to responsive or under a certain fixed device dimension, the equations rendered in KaTeX overflows out of the viewport as inspected in blue hightlight.

    katex overflowing on small screen devices
    ◎ katex overflowing on small screen devices

    This inevitably causes the viewport to break and extends the default width for KaTeX equations <div> to fit, users will be required to manually scroll right in order to view the full equation consequently as follows,

    katex overflowing with labels annotated
    ◎ katex overflowing with labels annotated

    The above situation is undoubtedly annoying for user experiences while reading documentation, consider at what scenarios users have to scroll, scroll and scroll only for viewing a single long-blocked equation, who would want to read such a text, right? But don't worry we have a simple fix for this situation via by several line of css.

    1.2: Temporary solution

    If you happened to search over KaTeX's official repo issue tracker on GitHub, there are several user-made css tweaks hack already, the fix is simple by adjusting the overflows of both x and y axes of the KaTeX render <div> blocks. The katex-display > .katex selector targets the child element of the .katex-display class that has the .katex class. This is the element that contains the KaTeX math expression. The first block of styles is mostly concerned with making sure that the KaTeX expression doesn't overflow its container and can be scrolled horizontally if needed. The second block of styles sets the font and line-height for the KaTeX expression and makes sure that its text is properly indented.

    But, the issue here is, the overflowing issue is resolved on the webpage, but the style itself left with a slight whitish "box" at the crossing corner of both horizontal as well as vertical scrollbar tracks, this might not be so explicit in the light mode of the webpage, but when it turns to dark mode, the box become annoying. Some people might say it's an easy tweak via setting the display property of the "box" element to display: none; to directly remove the box out of the page, this is a smart approach; however, while the box is gone, the two crossing tracks is going to form an untouched invisible box again against two bars without color. Thus, neither ways seems to perfectly solve the problem.

    1.3: Finding solution

    After running a quick research on Google, I found a simple hack tweak used in a theme of VuePress, vuepress-theme-hope on GitHub, the theme both integrate with KaTeX and MathJax for math supports.

    Under the styles directory of the repository, several line of scss styles came across my eyes,

    KaTeX tweak fix styles in theme
    ◎ KaTeX tweak fix styles in theme

    this scss lines only add a horizontal trackbar at the bottom of each overflowing equation while maximizing the vertical height of the equation, when user is on a small screened device as follows,

    Horizontal scrollbar of equations on small screens
    ◎ Horizontal scrollbar of equations on small screen

    Consequently, the fix is easy.

    1.4: Solution

    If you are running a documentation site like this version controlled via Node, especially VitePress without native scss supports, your fix would be installing scss support globally across the project, then add the scss styles and finally import the stylesheets to take effect globally.

    Install global scss support using your favored package manager.

    sh
    $ npm install -D scss
    $ npm install -D scss
    sh
    $ yarn add --dev scss
    $ yarn add --dev scss
    sh
    $ pnpm add -D scss
    $ pnpm add -D scss

    Then in your scss stylesheets, add the following and link or import them to your global styles, you should be off to go with a complete fix-up for KaTeX.

    scss
    ...
    -
    -// katex responsiveness fix
    -.katex {
    -  font-size: 1.05em;
    -  direction: ltr;
    -}
    -
    -.katex-display {
    -  overflow: auto hidden;
    -  -webkit-overflow-scrolling: touch;
    -  padding-top: 0.2em;
    -  padding-bottom: 0.2em;
    -
    -  &::-webkit-scrollbar {
    -    height: 3px;
    -  }
    -
    -  .katex {
    -    font-size: 1.21em;
    -  }
    -}
    -
    -.katex-error {
    -  color: #f00;
    -}
    -// katex responsiveness fix ends
    -
    -...
    ...
    -
    -// katex responsiveness fix
    -.katex {
    -  font-size: 1.05em;
    -  direction: ltr;
    -}
    -
    -.katex-display {
    -  overflow: auto hidden;
    -  -webkit-overflow-scrolling: touch;
    -  padding-top: 0.2em;
    -  padding-bottom: 0.2em;
    -
    -  &::-webkit-scrollbar {
    -    height: 3px;
    -  }
    -
    -  .katex {
    -    font-size: 1.21em;
    -  }
    -}
    -
    -.katex-error {
    -  color: #f00;
    -}
    -// katex responsiveness fix ends
    -
    -...

    Next, import your styles globally to take effect,

    scss
    @import '<your-scss-file>.scss';
    @import '<your-scss-file>.scss';

    1.4.1: Fix Explanation

    The first section sets the base styles for all KaTeX elements by increasing the font size slightly and ensuring that the text direction is left to right.

    The second section of code targets the KaTeX display elements specifically. This section adds a bit of padding to the top and bottom of the display elements and sets overflow to auto hidden, which allows the content to scroll inside the container horizontally if it overflows the container's width. The -webkit-overflow-scrolling property is added to ensure smooth scrolling on mobile devices.

    Additionally, this section contains a nested .katex selector, which increases the font size of the KaTeX elements within the display element.

    The third section targets the .katex-error class and sets the color to red to indicate that there is an error in rendering the LaTeX expression.

    1.5: What if I Don't Have SCSS?

    If you do not have native scss support for your site, such as a static HTML based documentation site or content management site builder such as Wiki.JS that works as an SaaS which only allows users to apply custom stylesheets within slots provided and make effects, you could use some scss to css converter online with options follows,

    to precompile from source scss into normal css styles and use them based on your needs, below are auto-generated compiled css, ONLY take it as reference, I do not guarantee the usability.

    css
    .katex {
    -    font-size: 1.05em;
    -    direction: ltr;
    -}
    -
    -.katex-display {
    -    overflow: auto hidden;
    -    -webkit-overflow-scrolling: touch;
    -    padding-top: 0.2em;
    -    padding-bottom: 0.2em;
    -}
    -.katex-display::-webkit-scrollbar {
    -    height: 3px;
    -}
    -.katex-display .katex {
    -    font-size: 1.21em;
    -}
    -
    -.katex-error {
    -    color: #f00;
    -}
    .katex {
    -    font-size: 1.05em;
    -    direction: ltr;
    -}
    -
    -.katex-display {
    -    overflow: auto hidden;
    -    -webkit-overflow-scrolling: touch;
    -    padding-top: 0.2em;
    -    padding-bottom: 0.2em;
    -}
    -.katex-display::-webkit-scrollbar {
    -    height: 3px;
    -}
    -.katex-display .katex {
    -    font-size: 1.21em;
    -}
    -
    -.katex-error {
    -    color: #f00;
    -}

    To be continued.

    `,39);function b(g,f,v,k,w,B){const a=n;return l(),o("div",null,[u,p(a,{readTime:"7",words:"1.2k"}),m])}const C=e(h,[["render",b]]);export{T as __pageData,C as default}; diff --git a/assets/application_markdown-it-katex_tips.md.d87fb855.js b/assets/application_markdown-it-katex_tips.md.d87fb855.js new file mode 100644 index 00000000..5dcfc05e --- /dev/null +++ b/assets/application_markdown-it-katex_tips.md.d87fb855.js @@ -0,0 +1,97 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as o,H as p,k as s,a as t,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const c="/assets/2023-03-22-17-04-25.d7c4c068.png",i="/assets/2023-03-22-20-29-28.39883b7f.png",y="/assets/2023-05-22-10-14-11.2c283da4.png",d="/assets/2023-05-22-10-27-47.c0db4fe7.png",w=JSON.parse('{"title":"Tips to Use markdown-it-katex","description":"Extra tips on using markdown-it-katex for the best experiences.","frontmatter":{"title":"Tips to Use markdown-it-katex","description":"Extra tips on using markdown-it-katex for the best experiences."},"headers":[],"relativePath":"application/markdown-it-katex/tips.md","filePath":"application/markdown-it-katex/tips.md","lastUpdated":1699051935000}'),h={name:"application/markdown-it-katex/tips.md"},u=s("h1",{id:"tips-hacks",tabindex:"-1"},[t("Tips & Hacks "),s("a",{class:"header-anchor",href:"#tips-hacks","aria-label":'Permalink to "Tips & Hacks"'},"​")],-1),b=r('

    1: Responsive KaTeX Styling

    1.1: Issue background

    KaTeX works out of the box on large screen devices such as laptops and desktop computers. But as KaTeX's built-in does not support responsiveness on it's default stylings, hence KaTeX equations might overflow out of the default width of the default application containers on small-screened mobile devices as you can see in the following image in the dev tool of chrome, when the dimension of the webpage is set to responsive or under a certain fixed device dimension, the equations rendered in KaTeX overflows out of the viewport as inspected in blue hightlight.

    katex overflowing on small screen devices
    ◎ katex overflowing on small screen devices

    This inevitably causes the viewport to break and extends the default width for KaTeX equations <div> to fit, users will be required to manually scroll right in order to view the full equation consequently as follows,

    katex overflowing with labels annotated
    ◎ katex overflowing with labels annotated

    The above situation is undoubtedly annoying for user experiences while reading documentation, consider at what scenarios users have to scroll, scroll and scroll only for viewing a single long-blocked equation, who would want to read such a text, right? But don't worry we have a simple fix for this situation via by several line of css.

    1.2: Temporary solution

    If you happened to search over KaTeX's official repo issue tracker on GitHub, there are several user-made css tweaks hack already, the fix is simple by adjusting the overflows of both x and y axes of the KaTeX render <div> blocks. The katex-display > .katex selector targets the child element of the .katex-display class that has the .katex class. This is the element that contains the KaTeX math expression. The first block of styles is mostly concerned with making sure that the KaTeX expression doesn't overflow its container and can be scrolled horizontally if needed. The second block of styles sets the font and line-height for the KaTeX expression and makes sure that its text is properly indented.

    @preview

    But, the issue here is, the overflowing issue is resolved on the webpage, but the style itself left with a slight whitish "box" at the crossing corner of both horizontal as well as vertical scrollbar tracks, this might not be so explicit in the light mode of the webpage, but when it turns to dark mode, the box become annoying. Some people might say it's an easy tweak via setting the display property of the "box" element to display: none; to directly remove the box out of the page, this is a smart approach; however, while the box is gone, the two crossing tracks is going to form an untouched invisible box again against two bars without color. Thus, neither ways seems to perfectly solve the problem.

    1.3: Finding solution

    After running a quick research on Google, I found a simple hack tweak used in a theme of VuePress, vuepress-theme-hope on GitHub, the theme both integrate with KaTeX and MathJax for math supports.

    @preview

    Under the styles directory of the repository, several line of scss styles came across my eyes,

    KaTeX tweak fix styles in theme
    ◎ KaTeX tweak fix styles in theme

    this scss lines only add a horizontal trackbar at the bottom of each overflowing equation while maximizing the vertical height of the equation, when user is on a small screened device as follows,

    Horizontal scrollbar of equations on small screens
    ◎ Horizontal scrollbar of equations on small screen

    Consequently, the fix is easy.

    1.4: Solution

    If you are running a documentation site like this version controlled via Node, especially VitePress without native scss supports, your fix would be installing scss support globally across the project, then add the scss styles and finally import the stylesheets to take effect globally.

    Install global scss support using your favored package manager.

    sh
    $ npm install -D scss
    $ npm install -D scss
    sh
    $ yarn add --dev scss
    $ yarn add --dev scss
    sh
    $ pnpm add -D scss
    $ pnpm add -D scss

    Then in your scss stylesheets, add the following and link or import them to your global styles, you should be off to go with a complete fix-up for KaTeX.

    scss
    ...
    +
    +// katex responsiveness fix
    +.katex {
    +  font-size: 1.05em;
    +  direction: ltr;
    +}
    +
    +.katex-display {
    +  overflow: auto hidden;
    +  -webkit-overflow-scrolling: touch;
    +  padding-top: 0.2em;
    +  padding-bottom: 0.2em;
    +
    +  &::-webkit-scrollbar {
    +    height: 3px;
    +  }
    +
    +  .katex {
    +    font-size: 1.21em;
    +  }
    +}
    +
    +.katex-error {
    +  color: #f00;
    +}
    +// katex responsiveness fix ends
    +
    +...
    ...
    +
    +// katex responsiveness fix
    +.katex {
    +  font-size: 1.05em;
    +  direction: ltr;
    +}
    +
    +.katex-display {
    +  overflow: auto hidden;
    +  -webkit-overflow-scrolling: touch;
    +  padding-top: 0.2em;
    +  padding-bottom: 0.2em;
    +
    +  &::-webkit-scrollbar {
    +    height: 3px;
    +  }
    +
    +  .katex {
    +    font-size: 1.21em;
    +  }
    +}
    +
    +.katex-error {
    +  color: #f00;
    +}
    +// katex responsiveness fix ends
    +
    +...

    Next, import your styles globally to take effect,

    scss
    @import '<your-scss-file>.scss';
    @import '<your-scss-file>.scss';

    1.4.1: Fix Explanation

    The first section sets the base styles for all KaTeX elements by increasing the font size slightly and ensuring that the text direction is left to right.

    The second section of code targets the KaTeX display elements specifically. This section adds a bit of padding to the top and bottom of the display elements and sets overflow to auto hidden, which allows the content to scroll inside the container horizontally if it overflows the container's width. The -webkit-overflow-scrolling property is added to ensure smooth scrolling on mobile devices.

    Additionally, this section contains a nested .katex selector, which increases the font size of the KaTeX elements within the display element.

    The third section targets the .katex-error class and sets the color to red to indicate that there is an error in rendering the LaTeX expression.

    1.5: What if I Don't Have SCSS?

    If you do not have native scss support for your site, such as a static HTML based documentation site or content management site builder such as Wiki.JS that works as an SaaS which only allows users to apply custom stylesheets within slots provided and make effects, you could use some scss to css converter online with options follows,

    to precompile from source scss into normal css styles and use them based on your needs, below are auto-generated compiled css, ONLY take it as reference, I do not guarantee the usability.

    css
    .katex {
    +    font-size: 1.05em;
    +    direction: ltr;
    +}
    +
    +.katex-display {
    +    overflow: auto hidden;
    +    -webkit-overflow-scrolling: touch;
    +    padding-top: 0.2em;
    +    padding-bottom: 0.2em;
    +}
    +.katex-display::-webkit-scrollbar {
    +    height: 3px;
    +}
    +.katex-display .katex {
    +    font-size: 1.21em;
    +}
    +
    +.katex-error {
    +    color: #f00;
    +}
    .katex {
    +    font-size: 1.05em;
    +    direction: ltr;
    +}
    +
    +.katex-display {
    +    overflow: auto hidden;
    +    -webkit-overflow-scrolling: touch;
    +    padding-top: 0.2em;
    +    padding-bottom: 0.2em;
    +}
    +.katex-display::-webkit-scrollbar {
    +    height: 3px;
    +}
    +.katex-display .katex {
    +    font-size: 1.21em;
    +}
    +
    +.katex-error {
    +    color: #f00;
    +}

    To be continued.

    `,39);function m(C,A,g,f,F,v){const a=n;return l(),o("div",null,[u,p(a,{readTime:"7",words:"1.2k"}),b])}const x=e(h,[["render",m]]);export{w as __pageData,x as default}; diff --git a/assets/application_markdown-it-katex_tips.md.4fa4c33c.lean.js b/assets/application_markdown-it-katex_tips.md.d87fb855.lean.js similarity index 58% rename from assets/application_markdown-it-katex_tips.md.4fa4c33c.lean.js rename to assets/application_markdown-it-katex_tips.md.d87fb855.lean.js index 2b1d2faa..5f48c0fa 100644 --- a/assets/application_markdown-it-katex_tips.md.4fa4c33c.lean.js +++ b/assets/application_markdown-it-katex_tips.md.d87fb855.lean.js @@ -1 +1 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as o,H as p,k as s,a as t,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const i="/assets/2023-03-22-17-04-25.d7c4c068.png",c="/assets/2023-03-22-20-29-28.39883b7f.png",d="/assets/2023-05-22-10-14-11.2c283da4.png",y="/assets/2023-05-22-10-27-47.c0db4fe7.png",T=JSON.parse('{"title":"Tips to Use markdown-it-katex","description":"Extra tips on using markdown-it-katex for the best experiences.","frontmatter":{"title":"Tips to Use markdown-it-katex","description":"Extra tips on using markdown-it-katex for the best experiences."},"headers":[],"relativePath":"application/markdown-it-katex/tips.md","filePath":"application/markdown-it-katex/tips.md","lastUpdated":1695377563000}'),h={name:"application/markdown-it-katex/tips.md"},u=s("h1",{id:"tips-hacks",tabindex:"-1"},[t("Tips & Hacks "),s("a",{class:"header-anchor",href:"#tips-hacks","aria-label":'Permalink to "Tips & Hacks"'},"​")],-1),m=r("",39);function b(g,f,v,k,w,B){const a=n;return l(),o("div",null,[u,p(a,{readTime:"7",words:"1.2k"}),m])}const C=e(h,[["render",b]]);export{T as __pageData,C as default}; +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as o,H as p,k as s,a as t,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const c="/assets/2023-03-22-17-04-25.d7c4c068.png",i="/assets/2023-03-22-20-29-28.39883b7f.png",y="/assets/2023-05-22-10-14-11.2c283da4.png",d="/assets/2023-05-22-10-27-47.c0db4fe7.png",w=JSON.parse('{"title":"Tips to Use markdown-it-katex","description":"Extra tips on using markdown-it-katex for the best experiences.","frontmatter":{"title":"Tips to Use markdown-it-katex","description":"Extra tips on using markdown-it-katex for the best experiences."},"headers":[],"relativePath":"application/markdown-it-katex/tips.md","filePath":"application/markdown-it-katex/tips.md","lastUpdated":1699051935000}'),h={name:"application/markdown-it-katex/tips.md"},u=s("h1",{id:"tips-hacks",tabindex:"-1"},[t("Tips & Hacks "),s("a",{class:"header-anchor",href:"#tips-hacks","aria-label":'Permalink to "Tips & Hacks"'},"​")],-1),b=r("",39);function m(C,A,g,f,F,v){const a=n;return l(),o("div",null,[u,p(a,{readTime:"7",words:"1.2k"}),b])}const x=e(h,[["render",m]]);export{w as __pageData,x as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.105e6b7f.js b/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.105e6b7f.js deleted file mode 100644 index 0846213b..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.105e6b7f.js +++ /dev/null @@ -1,94 +0,0 @@ -import{_ as c}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as d,o,c as t,H as l,k as s,w as p,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Hn=JSON.parse('{"title":"Meta Annotations","description":"Annotations provide a way to provide outside commentary on your code.","frontmatter":{"description":"Annotations provide a way to provide outside commentary on your code.","title":"Meta Annotations"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/annotations.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/annotations.md","lastUpdated":1695377563000}'),_={name:"application/vitepress-plugin-shiki-twoslash/api/annotations.md"},y=s("h1",{id:"queries",tabindex:"-1"},[a("Queries "),s("a",{class:"header-anchor",href:"#queries","aria-label":'Permalink to "Queries"'},"​")],-1),h=s("p",null,"Sometimes the thing you want to say is about the code, annotations provide a way to provide outside commentary on your code.",-1),u=s("h2",{id:"annotate-left-right-overrides-text",tabindex:"-1"},[s("code",null,"@annotate: [left|right] [overrides] - [text]"),a(),s("a",{class:"header-anchor",href:"#annotate-left-right-overrides-text","aria-label":'Permalink to "`@annotate: [left|right] [overrides] - [text]`"'},"​")],-1),m=s("p",null,"Annotate has a lot more controls than most of the other Twoslash commands, because each use of it probably needs to feel a bit different. Here's an example based on the TypeScript home page, click it to get it running so we can talk about what it does:",-1),g={class:"vp-code-group vp-adaptive-theme"},B=n('
    ',1),b={class:"blocks"},v={class:"language-ts vp-adaptive-theme active line-numbers-mode"},f=s("button",{title:"Copy Code",class:"copy"},null,-1),D=s("span",{class:"lang"},"ts",-1),T={class:"language-ts"},w={class:"tag-container"},q={class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},A=s("div",{class:"language-id"},"ts",-1),C={class:"code-container"},x=s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#839496"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),k={class:"line"},S=s("span",{style:{color:"#839496"}}," ",-1),I=s("span",{style:{color:"#859900"}},"if",-1),P=s("span",{style:{color:"#839496"}}," (",-1),E={style:{color:"#268BD2"}},V=s("data-lsp",{lsp:"any"},"orr",-1),N=s("span",{style:{color:"#839496"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),R=n('> 10) return ',6),M=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),z=s("span",{style:{color:"#839496"}},".",-1),X=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),F=n('(0, 10)',5),Y=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),L=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),W=s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),$=s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")],-1),H={class:"twoslash-annotation left",style:{top:"0rem"}},O={style:{transform:"translateX(8px) translateY(27px) rotate(90deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Q=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),G=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),J={class:"tag-container"},U={class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},Z=s("div",{class:"language-id"},"ts",-1),j={class:"code-container"},K=s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#657B83"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),ss={class:"line"},as=s("span",{style:{color:"#657B83"}}," ",-1),ns=s("span",{style:{color:"#859900"}},"if",-1),os=s("span",{style:{color:"#657B83"}}," (",-1),ts={style:{color:"#268BD2"}},ls=s("data-lsp",{lsp:"any"},"orr",-1),es=s("span",{style:{color:"#657B83"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),ps=n('> 10) return ',6),rs=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),cs=s("span",{style:{color:"#657B83"}},".",-1),is=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ds=n('(0, 10)',5),_s=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),ys=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),hs=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),us=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")],-1),ms={class:"twoslash-annotation left",style:{top:"0rem"}},gs={style:{transform:"translateX(8px) translateY(27px) rotate(90deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Bs=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),bs=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),vs=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),fs=n(`
    md
    \`\`\`ts twoslash
    -// @errors: 2304
    -// @strict: false
    -
    -function compact(arr) {
    -    if (orr.length > 10) return arr.trim(0, 10)
    -    return arr
    -}
    -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    -\`\`\`
    \`\`\`ts twoslash
    -// @errors: 2304
    -// @strict: false
    -
    -function compact(arr) {
    -    if (orr.length > 10) return arr.trim(0, 10)
    -    return arr
    -}
    -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    -\`\`\`
    `,1),Ds=n("

    First up, cool — it adds some text to the left hand side of the code. It features quite a few different options, so lets go through them one by one:

    • left or right: It's currently left. It's worth noting the arrow flips also, and 90deg isn't a great option. Let's look at that next.

    • { "arrrowRot": "90deg 8px 27px" } - This JSON object is used to manipulate the annotation, you have 3 controls for arrow positioning and rotation: degrees x y. I recommend keeping those in degrees and px, but it's your life. These are overrides from defaults which are okay, but not really something you ever want to ship.

    • { "textDegree": "3deg" } - Rotates the text, you probably want something between -3deg and 3deg. Optional, defaults to 0.

    • { "top": "0rem" } - Sets the y coordinates for the annotation relative to the code sample, if it's not included then it becomes [lineNum]rem.

    What's not included in this sample is flipped, which can be used to flip the arrow's orientation. Here's some examples:

    A horizontal right example:

    ",4),Ts={class:"vp-code-group vp-adaptive-theme"},ws=n('
    ',1),qs={class:"blocks"},As={class:"language-ts vp-adaptive-theme active line-numbers-mode"},Cs=s("button",{title:"Copy Code",class:"copy"},null,-1),xs=s("span",{class:"lang"},"ts",-1),ks={class:"language-ts"},Ss={class:"tag-container"},Is={class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},Ps=s("div",{class:"language-id"},"ts",-1),Es={class:"code-container"},Vs=s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#839496"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),Ns={class:"line"},Rs=s("span",{style:{color:"#839496"}}," ",-1),Ms=s("span",{style:{color:"#859900"}},"if",-1),zs=s("span",{style:{color:"#839496"}}," (",-1),Xs={style:{color:"#268BD2"}},Fs=s("data-lsp",{lsp:"any"},"orr",-1),Ys=s("span",{style:{color:"#839496"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),Ls=n('> 10) return ',6),Ws=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),$s=s("span",{style:{color:"#839496"}},".",-1),Hs=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),Os=n('(0, 10)',5),Qs=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),Gs=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),Js=s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),Us=s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")],-1),Zs={class:"twoslash-annotation right",style:{top:"3rem"}},js={style:{transform:"translateX(-10px) translateY(-10px) rotate(-50deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Ks=s("path",{d:"M27 39C26.5 32.7511 21.9 17.5173 7.5 6.57333M16.5 4.04L0.999999 0.999998C3.16667 4.88444 7.5 13.16 7.5 15.1867",stroke:"black"},null,-1),sa=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(0deg)"}},"Discovered a typo, the param is arr, not orr!",-1),aa={class:"tag-container"},na={class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},oa=s("div",{class:"language-id"},"ts",-1),ta={class:"code-container"},la=s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#657B83"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),ea={class:"line"},pa=s("span",{style:{color:"#657B83"}}," ",-1),ra=s("span",{style:{color:"#859900"}},"if",-1),ca=s("span",{style:{color:"#657B83"}}," (",-1),ia={style:{color:"#268BD2"}},da=s("data-lsp",{lsp:"any"},"orr",-1),_a=s("span",{style:{color:"#657B83"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),ya=n('> 10) return ',6),ha=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),ua=s("span",{style:{color:"#657B83"}},".",-1),ma=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ga=n('(0, 10)',5),Ba=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),ba=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),va=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),fa=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")],-1),Da={class:"twoslash-annotation right",style:{top:"3rem"}},Ta={style:{transform:"translateX(-10px) translateY(-10px) rotate(-50deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},wa=s("path",{d:"M27 39C26.5 32.7511 21.9 17.5173 7.5 6.57333M16.5 4.04L0.999999 0.999998C3.16667 4.88444 7.5 13.16 7.5 15.1867",stroke:"black"},null,-1),qa=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(0deg)"}},"Discovered a typo, the param is arr, not orr!",-1),Aa=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),Ca=n(`
    md
    \`\`\`ts twoslash
    -// @errors: 2304
    -// @strict: false
    -
    -function compact(arr) {
    -    if (orr.length > 10) return arr.trim(0, 10)
    -    return arr
    -}
    -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    -\`\`\`
    \`\`\`ts twoslash
    -// @errors: 2304
    -// @strict: false
    -
    -function compact(arr) {
    -    if (orr.length > 10) return arr.trim(0, 10)
    -    return arr
    -}
    -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    -\`\`\`
    `,1),xa=s("p",null,"Upside down arrow pointing at the error, using flipped to re-flip the arrow:",-1),ka={class:"vp-code-group vp-adaptive-theme"},Sa=n('
    ',1),Ia={class:"blocks"},Pa={class:"language-ts vp-adaptive-theme active line-numbers-mode"},Ea=s("button",{title:"Copy Code",class:"copy"},null,-1),Va=s("span",{class:"lang"},"ts",-1),Na={class:"language-ts"},Ra={class:"tag-container"},Ma={class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},za=s("div",{class:"language-id"},"ts",-1),Xa={class:"code-container"},Fa=s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#839496"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),Ya={class:"line"},La=s("span",{style:{color:"#839496"}}," ",-1),Wa=s("span",{style:{color:"#859900"}},"if",-1),$a=s("span",{style:{color:"#839496"}}," (",-1),Ha={style:{color:"#268BD2"}},Oa=s("data-lsp",{lsp:"any"},"orr",-1),Qa=s("span",{style:{color:"#839496"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),Ga=n('> 10) return ',6),Ja=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),Ua=s("span",{style:{color:"#839496"}},".",-1),Za=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ja=n('(0, 10)',5),Ka=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),sn=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),an=s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),nn=s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")],-1),on={class:"twoslash-annotation right",style:{top:"-0.7rem"}},tn={style:{transform:"translateX(8px) translateY(46px) rotate(190deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},ln=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),en=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(-3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),pn={class:"tag-container"},rn={class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},cn=s("div",{class:"language-id"},"ts",-1),dn={class:"code-container"},_n=s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#657B83"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),yn={class:"line"},hn=s("span",{style:{color:"#657B83"}}," ",-1),un=s("span",{style:{color:"#859900"}},"if",-1),mn=s("span",{style:{color:"#657B83"}}," (",-1),gn={style:{color:"#268BD2"}},Bn=s("data-lsp",{lsp:"any"},"orr",-1),bn=s("span",{style:{color:"#657B83"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),vn=n('> 10) return ',6),fn=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),Dn=s("span",{style:{color:"#657B83"}},".",-1),Tn=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),wn=n('(0, 10)',5),qn=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),An=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),Cn=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),xn=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")],-1),kn={class:"twoslash-annotation right",style:{top:"-0.7rem"}},Sn={style:{transform:"translateX(8px) translateY(46px) rotate(190deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},In=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),Pn=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(-3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),En=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),Vn=n(`
    md
    \`\`\`ts twoslash
    -// @errors: 2304
    -// @strict: false
    -
    -function compact(arr) {
    -    if (orr.length > 10) return arr.trim(0, 10)
    -    return arr
    -}
    -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    -\`\`\`
    \`\`\`ts twoslash
    -// @errors: 2304
    -// @strict: false
    -
    -function compact(arr) {
    -    if (orr.length > 10) return arr.trim(0, 10)
    -    return arr
    -}
    -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    -\`\`\`
    `,1);function Nn(Rn,Mn,zn,Xn,Fn,Yn){const r=c,e=d("data-err");return o(),t("div",null,[y,l(r,{readTime:"3",words:"541"}),h,u,m,s("div",g,[B,s("div",b,[s("div",v,[f,D,s("pre",null,[s("code",T,[s("div",w,[s("pre",q,[A,s("div",C,[s("code",null,[x,s("div",k,[S,I,P,s("span",E,[l(e,null,{default:p(()=>[V]),_:1})]),N,R,M,z,X,F]),Y,L,W,$])])]),a(` -`),s("div",H,[a(` - `),(o(),t("svg",O,[a(` - `),Q,a(` -`)])),a(` - `),G,a(` -`)])]),a(` -`),s("div",J,[s("pre",U,[Z,s("div",j,[s("code",null,[K,s("div",ss,[as,ns,os,s("span",ts,[l(e,null,{default:p(()=>[ls]),_:1})]),es,ps,rs,cs,is,ds]),_s,ys,hs,us])])]),a(` -`),s("div",ms,[a(` - `),(o(),t("svg",gs,[a(` - `),Bs,a(` -`)])),a(` - `),bs,a(` -`)])])])]),vs]),fs])]),Ds,s("div",Ts,[ws,s("div",qs,[s("div",As,[Cs,xs,s("pre",null,[s("code",ks,[s("div",Ss,[s("pre",Is,[Ps,s("div",Es,[s("code",null,[Vs,s("div",Ns,[Rs,Ms,zs,s("span",Xs,[l(e,null,{default:p(()=>[Fs]),_:1})]),Ys,Ls,Ws,$s,Hs,Os]),Qs,Gs,Js,Us])])]),a(` -`),s("div",Zs,[a(` - `),(o(),t("svg",js,[a(` - `),Ks,a(` -`)])),a(` - `),sa,a(` -`)])]),a(` -`),s("div",aa,[s("pre",na,[oa,s("div",ta,[s("code",null,[la,s("div",ea,[pa,ra,ca,s("span",ia,[l(e,null,{default:p(()=>[da]),_:1})]),_a,ya,ha,ua,ma,ga]),Ba,ba,va,fa])])]),a(` -`),s("div",Da,[a(` - `),(o(),t("svg",Ta,[a(` - `),wa,a(` -`)])),a(` - `),qa,a(` -`)])])])]),Aa]),Ca])]),xa,s("div",ka,[Sa,s("div",Ia,[s("div",Pa,[Ea,Va,s("pre",null,[s("code",Na,[s("div",Ra,[s("pre",Ma,[za,s("div",Xa,[s("code",null,[Fa,s("div",Ya,[La,Wa,$a,s("span",Ha,[l(e,null,{default:p(()=>[Oa]),_:1})]),Qa,Ga,Ja,Ua,Za,ja]),Ka,sn,an,nn])])]),a(` -`),s("div",on,[a(` - `),(o(),t("svg",tn,[a(` - `),ln,a(` -`)])),a(` - `),en,a(` -`)])]),a(` -`),s("div",pn,[s("pre",rn,[cn,s("div",dn,[s("code",null,[_n,s("div",yn,[hn,un,mn,s("span",gn,[l(e,null,{default:p(()=>[Bn]),_:1})]),bn,vn,fn,Dn,Tn,wn]),qn,An,Cn,xn])])]),a(` -`),s("div",kn,[a(` - `),(o(),t("svg",Sn,[a(` - `),In,a(` -`)])),a(` - `),Pn,a(` -`)])])])]),En]),Vn])])])}const On=i(_,[["render",Nn]]);export{Hn as __pageData,On as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.105e6b7f.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.105e6b7f.lean.js deleted file mode 100644 index 1fc8efaf..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.105e6b7f.lean.js +++ /dev/null @@ -1,40 +0,0 @@ -import{_ as c}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as d,o,c as t,H as l,k as s,w as p,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Hn=JSON.parse('{"title":"Meta Annotations","description":"Annotations provide a way to provide outside commentary on your code.","frontmatter":{"description":"Annotations provide a way to provide outside commentary on your code.","title":"Meta Annotations"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/annotations.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/annotations.md","lastUpdated":1695377563000}'),_={name:"application/vitepress-plugin-shiki-twoslash/api/annotations.md"},y=s("h1",{id:"queries",tabindex:"-1"},[a("Queries "),s("a",{class:"header-anchor",href:"#queries","aria-label":'Permalink to "Queries"'},"​")],-1),h=s("p",null,"Sometimes the thing you want to say is about the code, annotations provide a way to provide outside commentary on your code.",-1),u=s("h2",{id:"annotate-left-right-overrides-text",tabindex:"-1"},[s("code",null,"@annotate: [left|right] [overrides] - [text]"),a(),s("a",{class:"header-anchor",href:"#annotate-left-right-overrides-text","aria-label":'Permalink to "`@annotate: [left|right] [overrides] - [text]`"'},"​")],-1),m=s("p",null,"Annotate has a lot more controls than most of the other Twoslash commands, because each use of it probably needs to feel a bit different. Here's an example based on the TypeScript home page, click it to get it running so we can talk about what it does:",-1),g={class:"vp-code-group vp-adaptive-theme"},B=n("",1),b={class:"blocks"},v={class:"language-ts vp-adaptive-theme active line-numbers-mode"},f=s("button",{title:"Copy Code",class:"copy"},null,-1),D=s("span",{class:"lang"},"ts",-1),T={class:"language-ts"},w={class:"tag-container"},q={class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},A=s("div",{class:"language-id"},"ts",-1),C={class:"code-container"},x=s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#839496"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),k={class:"line"},S=s("span",{style:{color:"#839496"}}," ",-1),I=s("span",{style:{color:"#859900"}},"if",-1),P=s("span",{style:{color:"#839496"}}," (",-1),E={style:{color:"#268BD2"}},V=s("data-lsp",{lsp:"any"},"orr",-1),N=s("span",{style:{color:"#839496"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),R=n("",6),M=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),z=s("span",{style:{color:"#839496"}},".",-1),X=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),F=n("",5),Y=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),L=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),W=s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),$=s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")],-1),H={class:"twoslash-annotation left",style:{top:"0rem"}},O={style:{transform:"translateX(8px) translateY(27px) rotate(90deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Q=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),G=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),J={class:"tag-container"},U={class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},Z=s("div",{class:"language-id"},"ts",-1),j={class:"code-container"},K=s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#657B83"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),ss={class:"line"},as=s("span",{style:{color:"#657B83"}}," ",-1),ns=s("span",{style:{color:"#859900"}},"if",-1),os=s("span",{style:{color:"#657B83"}}," (",-1),ts={style:{color:"#268BD2"}},ls=s("data-lsp",{lsp:"any"},"orr",-1),es=s("span",{style:{color:"#657B83"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),ps=n("",6),rs=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),cs=s("span",{style:{color:"#657B83"}},".",-1),is=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ds=n("",5),_s=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),ys=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),hs=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),us=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")],-1),ms={class:"twoslash-annotation left",style:{top:"0rem"}},gs={style:{transform:"translateX(8px) translateY(27px) rotate(90deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Bs=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),bs=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),vs=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),fs=n("",1),Ds=n("",4),Ts={class:"vp-code-group vp-adaptive-theme"},ws=n("",1),qs={class:"blocks"},As={class:"language-ts vp-adaptive-theme active line-numbers-mode"},Cs=s("button",{title:"Copy Code",class:"copy"},null,-1),xs=s("span",{class:"lang"},"ts",-1),ks={class:"language-ts"},Ss={class:"tag-container"},Is={class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},Ps=s("div",{class:"language-id"},"ts",-1),Es={class:"code-container"},Vs=s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#839496"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),Ns={class:"line"},Rs=s("span",{style:{color:"#839496"}}," ",-1),Ms=s("span",{style:{color:"#859900"}},"if",-1),zs=s("span",{style:{color:"#839496"}}," (",-1),Xs={style:{color:"#268BD2"}},Fs=s("data-lsp",{lsp:"any"},"orr",-1),Ys=s("span",{style:{color:"#839496"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),Ls=n("",6),Ws=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),$s=s("span",{style:{color:"#839496"}},".",-1),Hs=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),Os=n("",5),Qs=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),Gs=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),Js=s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),Us=s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")],-1),Zs={class:"twoslash-annotation right",style:{top:"3rem"}},js={style:{transform:"translateX(-10px) translateY(-10px) rotate(-50deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Ks=s("path",{d:"M27 39C26.5 32.7511 21.9 17.5173 7.5 6.57333M16.5 4.04L0.999999 0.999998C3.16667 4.88444 7.5 13.16 7.5 15.1867",stroke:"black"},null,-1),sa=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(0deg)"}},"Discovered a typo, the param is arr, not orr!",-1),aa={class:"tag-container"},na={class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},oa=s("div",{class:"language-id"},"ts",-1),ta={class:"code-container"},la=s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#657B83"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),ea={class:"line"},pa=s("span",{style:{color:"#657B83"}}," ",-1),ra=s("span",{style:{color:"#859900"}},"if",-1),ca=s("span",{style:{color:"#657B83"}}," (",-1),ia={style:{color:"#268BD2"}},da=s("data-lsp",{lsp:"any"},"orr",-1),_a=s("span",{style:{color:"#657B83"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),ya=n("",6),ha=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),ua=s("span",{style:{color:"#657B83"}},".",-1),ma=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ga=n("",5),Ba=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),ba=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),va=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),fa=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")],-1),Da={class:"twoslash-annotation right",style:{top:"3rem"}},Ta={style:{transform:"translateX(-10px) translateY(-10px) rotate(-50deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},wa=s("path",{d:"M27 39C26.5 32.7511 21.9 17.5173 7.5 6.57333M16.5 4.04L0.999999 0.999998C3.16667 4.88444 7.5 13.16 7.5 15.1867",stroke:"black"},null,-1),qa=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(0deg)"}},"Discovered a typo, the param is arr, not orr!",-1),Aa=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),Ca=n("",1),xa=s("p",null,"Upside down arrow pointing at the error, using flipped to re-flip the arrow:",-1),ka={class:"vp-code-group vp-adaptive-theme"},Sa=n("",1),Ia={class:"blocks"},Pa={class:"language-ts vp-adaptive-theme active line-numbers-mode"},Ea=s("button",{title:"Copy Code",class:"copy"},null,-1),Va=s("span",{class:"lang"},"ts",-1),Na={class:"language-ts"},Ra={class:"tag-container"},Ma={class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},za=s("div",{class:"language-id"},"ts",-1),Xa={class:"code-container"},Fa=s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#839496"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),Ya={class:"line"},La=s("span",{style:{color:"#839496"}}," ",-1),Wa=s("span",{style:{color:"#859900"}},"if",-1),$a=s("span",{style:{color:"#839496"}}," (",-1),Ha={style:{color:"#268BD2"}},Oa=s("data-lsp",{lsp:"any"},"orr",-1),Qa=s("span",{style:{color:"#839496"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),Ga=n("",6),Ja=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),Ua=s("span",{style:{color:"#839496"}},".",-1),Za=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ja=n("",5),Ka=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),sn=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),an=s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),nn=s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")],-1),on={class:"twoslash-annotation right",style:{top:"-0.7rem"}},tn={style:{transform:"translateX(8px) translateY(46px) rotate(190deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},ln=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),en=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(-3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),pn={class:"tag-container"},rn={class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},cn=s("div",{class:"language-id"},"ts",-1),dn={class:"code-container"},_n=s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#657B83"}},[a("("),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(") {")])],-1),yn={class:"line"},hn=s("span",{style:{color:"#657B83"}}," ",-1),un=s("span",{style:{color:"#859900"}},"if",-1),mn=s("span",{style:{color:"#657B83"}}," (",-1),gn={style:{color:"#268BD2"}},Bn=s("data-lsp",{lsp:"any"},"orr",-1),bn=s("span",{style:{color:"#657B83"}},[a("."),s("data-lsp",{lsp:"any"},"length"),a()],-1),vn=n("",6),fn=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")],-1),Dn=s("span",{style:{color:"#657B83"}},".",-1),Tn=s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"trim")],-1),wn=n("",5),qn=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),An=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),Cn=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"return"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),xn=s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")],-1),kn={class:"twoslash-annotation right",style:{top:"-0.7rem"}},Sn={style:{transform:"translateX(8px) translateY(46px) rotate(190deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},In=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),Pn=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(-3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),En=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),Vn=n("",1);function Nn(Rn,Mn,zn,Xn,Fn,Yn){const r=c,e=d("data-err");return o(),t("div",null,[y,l(r,{readTime:"3",words:"541"}),h,u,m,s("div",g,[B,s("div",b,[s("div",v,[f,D,s("pre",null,[s("code",T,[s("div",w,[s("pre",q,[A,s("div",C,[s("code",null,[x,s("div",k,[S,I,P,s("span",E,[l(e,null,{default:p(()=>[V]),_:1})]),N,R,M,z,X,F]),Y,L,W,$])])]),a(` -`),s("div",H,[a(` - `),(o(),t("svg",O,[a(` - `),Q,a(` -`)])),a(` - `),G,a(` -`)])]),a(` -`),s("div",J,[s("pre",U,[Z,s("div",j,[s("code",null,[K,s("div",ss,[as,ns,os,s("span",ts,[l(e,null,{default:p(()=>[ls]),_:1})]),es,ps,rs,cs,is,ds]),_s,ys,hs,us])])]),a(` -`),s("div",ms,[a(` - `),(o(),t("svg",gs,[a(` - `),Bs,a(` -`)])),a(` - `),bs,a(` -`)])])])]),vs]),fs])]),Ds,s("div",Ts,[ws,s("div",qs,[s("div",As,[Cs,xs,s("pre",null,[s("code",ks,[s("div",Ss,[s("pre",Is,[Ps,s("div",Es,[s("code",null,[Vs,s("div",Ns,[Rs,Ms,zs,s("span",Xs,[l(e,null,{default:p(()=>[Fs]),_:1})]),Ys,Ls,Ws,$s,Hs,Os]),Qs,Gs,Js,Us])])]),a(` -`),s("div",Zs,[a(` - `),(o(),t("svg",js,[a(` - `),Ks,a(` -`)])),a(` - `),sa,a(` -`)])]),a(` -`),s("div",aa,[s("pre",na,[oa,s("div",ta,[s("code",null,[la,s("div",ea,[pa,ra,ca,s("span",ia,[l(e,null,{default:p(()=>[da]),_:1})]),_a,ya,ha,ua,ma,ga]),Ba,ba,va,fa])])]),a(` -`),s("div",Da,[a(` - `),(o(),t("svg",Ta,[a(` - `),wa,a(` -`)])),a(` - `),qa,a(` -`)])])])]),Aa]),Ca])]),xa,s("div",ka,[Sa,s("div",Ia,[s("div",Pa,[Ea,Va,s("pre",null,[s("code",Na,[s("div",Ra,[s("pre",Ma,[za,s("div",Xa,[s("code",null,[Fa,s("div",Ya,[La,Wa,$a,s("span",Ha,[l(e,null,{default:p(()=>[Oa]),_:1})]),Qa,Ga,Ja,Ua,Za,ja]),Ka,sn,an,nn])])]),a(` -`),s("div",on,[a(` - `),(o(),t("svg",tn,[a(` - `),ln,a(` -`)])),a(` - `),en,a(` -`)])]),a(` -`),s("div",pn,[s("pre",rn,[cn,s("div",dn,[s("code",null,[_n,s("div",yn,[hn,un,mn,s("span",gn,[l(e,null,{default:p(()=>[Bn]),_:1})]),bn,vn,fn,Dn,Tn,wn]),qn,An,Cn,xn])])]),a(` -`),s("div",kn,[a(` - `),(o(),t("svg",Sn,[a(` - `),In,a(` -`)])),a(` - `),Pn,a(` -`)])])])]),En]),Vn])])])}const On=i(_,[["render",Nn]]);export{Hn as __pageData,On as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.a42ad2a7.js b/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.a42ad2a7.js new file mode 100644 index 00000000..b02e532e --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.a42ad2a7.js @@ -0,0 +1,94 @@ +import{_ as c}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as d,o,c as t,H as e,k as s,a,w as p,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Vn=JSON.parse('{"title":"Meta Annotations","description":"Annotations provide a way to provide outside commentary on your code.","frontmatter":{"description":"Annotations provide a way to provide outside commentary on your code.","title":"Meta Annotations"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/annotations.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/annotations.md","lastUpdated":1699051935000}'),_={name:"application/vitepress-plugin-shiki-twoslash/api/annotations.md"},y=s("h1",{id:"queries",tabindex:"-1"},[a("Queries "),s("a",{class:"header-anchor",href:"#queries","aria-label":'Permalink to "Queries"'},"​")],-1),h=s("p",null,"Sometimes the thing you want to say is about the code, annotations provide a way to provide outside commentary on your code.",-1),u=s("h2",{id:"annotate-left-right-overrides-text",tabindex:"-1"},[s("code",null,"@annotate: [left|right] [overrides] - [text]"),a(),s("a",{class:"header-anchor",href:"#annotate-left-right-overrides-text","aria-label":'Permalink to "`@annotate: [left|right] [overrides] - [text]`"'},"​")],-1),A=s("p",null,"Annotate has a lot more controls than most of the other Twoslash commands, because each use of it probably needs to feel a bit different. Here's an example based on the TypeScript home page, click it to get it running so we can talk about what it does:",-1),C={class:"vp-code-group vp-adaptive-theme"},m=n('
    ',1),D={class:"blocks"},g={class:"language-ts vp-adaptive-theme active line-numbers-mode"},b=s("button",{title:"Copy Code",class:"copy"},null,-1),v=s("span",{class:"lang"},"ts",-1),B={class:"language-ts"},f={class:"tag-container"},E={class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},T=s("div",{class:"language-id"},"ts",-1),F={class:"code-container"},w=s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#ADBAC7"}},") {")],-1),q={class:"line"},x=s("span",{style:{color:"#ADBAC7"}}," ",-1),k=s("span",{style:{color:"#F47067"}},"if",-1),S={style:{color:"#ADBAC7"}},V=s("data-lsp",{lsp:"any"},"orr",-1),I=s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"any"},"length")],-1),P=n(' > 10) return',6),N=s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),R=s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"any"},"trim")],-1),M=n('(0, 10)',5),L=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),X=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),Y=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),O=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")],-1),$={class:"twoslash-annotation left",style:{top:"0rem"}},j={style:{transform:"translateX(8px) translateY(27px) rotate(90deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},H=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),Q=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),J={class:"tag-container"},K={class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},U=s("div",{class:"language-id"},"ts",-1),Z={class:"code-container"},z=s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#24292E"}},") {")],-1),W={class:"line"},G=s("span",{style:{color:"#24292E"}}," ",-1),ss=s("span",{style:{color:"#D73A49"}},"if",-1),as={style:{color:"#24292E"}},ns=s("data-lsp",{lsp:"any"},"orr",-1),os=s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"length")],-1),ts=n(' > 10) return',6),es=s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),ls=s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ps=n('(0, 10)',5),rs=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),cs=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),is=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"return"),s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),ds=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")],-1),_s={class:"twoslash-annotation left",style:{top:"0rem"}},ys={style:{transform:"translateX(8px) translateY(27px) rotate(90deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},hs=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),us=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),As=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),Cs=n(`
    md
    \`\`\`ts twoslash
    +// @errors: 2304
    +// @strict: false
    +
    +function compact(arr) {
    +    if (orr.length > 10) return arr.trim(0, 10)
    +    return arr
    +}
    +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    +\`\`\`
    \`\`\`ts twoslash
    +// @errors: 2304
    +// @strict: false
    +
    +function compact(arr) {
    +    if (orr.length > 10) return arr.trim(0, 10)
    +    return arr
    +}
    +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    +\`\`\`
    `,1),ms=n("

    First up, cool — it adds some text to the left hand side of the code. It features quite a few different options, so lets go through them one by one:

    • left or right: It's currently left. It's worth noting the arrow flips also, and 90deg isn't a great option. Let's look at that next.

    • { "arrrowRot": "90deg 8px 27px" } - This JSON object is used to manipulate the annotation, you have 3 controls for arrow positioning and rotation: degrees x y. I recommend keeping those in degrees and px, but it's your life. These are overrides from defaults which are okay, but not really something you ever want to ship.

    • { "textDegree": "3deg" } - Rotates the text, you probably want something between -3deg and 3deg. Optional, defaults to 0.

    • { "top": "0rem" } - Sets the y coordinates for the annotation relative to the code sample, if it's not included then it becomes [lineNum]rem.

    What's not included in this sample is flipped, which can be used to flip the arrow's orientation. Here's some examples:

    A horizontal right example:

    ",4),Ds={class:"vp-code-group vp-adaptive-theme"},gs=n('
    ',1),bs={class:"blocks"},vs={class:"language-ts vp-adaptive-theme active line-numbers-mode"},Bs=s("button",{title:"Copy Code",class:"copy"},null,-1),fs=s("span",{class:"lang"},"ts",-1),Es={class:"language-ts"},Ts={class:"tag-container"},Fs={class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},ws=s("div",{class:"language-id"},"ts",-1),qs={class:"code-container"},xs=s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#ADBAC7"}},") {")],-1),ks={class:"line"},Ss=s("span",{style:{color:"#ADBAC7"}}," ",-1),Vs=s("span",{style:{color:"#F47067"}},"if",-1),Is={style:{color:"#ADBAC7"}},Ps=s("data-lsp",{lsp:"any"},"orr",-1),Ns=s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"any"},"length")],-1),Rs=n(' > 10) return',6),Ms=s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),Ls=s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"any"},"trim")],-1),Xs=n('(0, 10)',5),Ys=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),Os=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),$s=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),js=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")],-1),Hs={class:"twoslash-annotation right",style:{top:"3rem"}},Qs={style:{transform:"translateX(-10px) translateY(-10px) rotate(-50deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Js=s("path",{d:"M27 39C26.5 32.7511 21.9 17.5173 7.5 6.57333M16.5 4.04L0.999999 0.999998C3.16667 4.88444 7.5 13.16 7.5 15.1867",stroke:"black"},null,-1),Ks=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(0deg)"}},"Discovered a typo, the param is arr, not orr!",-1),Us={class:"tag-container"},Zs={class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},zs=s("div",{class:"language-id"},"ts",-1),Ws={class:"code-container"},Gs=s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#24292E"}},") {")],-1),sa={class:"line"},aa=s("span",{style:{color:"#24292E"}}," ",-1),na=s("span",{style:{color:"#D73A49"}},"if",-1),oa={style:{color:"#24292E"}},ta=s("data-lsp",{lsp:"any"},"orr",-1),ea=s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"length")],-1),la=n(' > 10) return',6),pa=s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),ra=s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ca=n('(0, 10)',5),ia=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),da=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),_a=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"return"),s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),ya=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")],-1),ha={class:"twoslash-annotation right",style:{top:"3rem"}},ua={style:{transform:"translateX(-10px) translateY(-10px) rotate(-50deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Aa=s("path",{d:"M27 39C26.5 32.7511 21.9 17.5173 7.5 6.57333M16.5 4.04L0.999999 0.999998C3.16667 4.88444 7.5 13.16 7.5 15.1867",stroke:"black"},null,-1),Ca=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(0deg)"}},"Discovered a typo, the param is arr, not orr!",-1),ma=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),Da=n(`
    md
    \`\`\`ts twoslash
    +// @errors: 2304
    +// @strict: false
    +
    +function compact(arr) {
    +    if (orr.length > 10) return arr.trim(0, 10)
    +    return arr
    +}
    +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    +\`\`\`
    \`\`\`ts twoslash
    +// @errors: 2304
    +// @strict: false
    +
    +function compact(arr) {
    +    if (orr.length > 10) return arr.trim(0, 10)
    +    return arr
    +}
    +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    +\`\`\`
    `,1),ga=s("p",null,"Upside down arrow pointing at the error, using flipped to re-flip the arrow:",-1),ba={class:"vp-code-group vp-adaptive-theme"},va=n('
    ',1),Ba={class:"blocks"},fa={class:"language-ts vp-adaptive-theme active line-numbers-mode"},Ea=s("button",{title:"Copy Code",class:"copy"},null,-1),Ta=s("span",{class:"lang"},"ts",-1),Fa={class:"language-ts"},wa={class:"tag-container"},qa={class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},xa=s("div",{class:"language-id"},"ts",-1),ka={class:"code-container"},Sa=s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#ADBAC7"}},") {")],-1),Va={class:"line"},Ia=s("span",{style:{color:"#ADBAC7"}}," ",-1),Pa=s("span",{style:{color:"#F47067"}},"if",-1),Na={style:{color:"#ADBAC7"}},Ra=s("data-lsp",{lsp:"any"},"orr",-1),Ma=s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"any"},"length")],-1),La=n(' > 10) return',6),Xa=s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),Ya=s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"any"},"trim")],-1),Oa=n('(0, 10)',5),$a=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),ja=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),Ha=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),Qa=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")],-1),Ja={class:"twoslash-annotation right",style:{top:"-0.7rem"}},Ka={style:{transform:"translateX(8px) translateY(46px) rotate(190deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Ua=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),Za=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(-3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),za={class:"tag-container"},Wa={class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},Ga=s("div",{class:"language-id"},"ts",-1),sn={class:"code-container"},an=s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#24292E"}},") {")],-1),nn={class:"line"},on=s("span",{style:{color:"#24292E"}}," ",-1),tn=s("span",{style:{color:"#D73A49"}},"if",-1),en={style:{color:"#24292E"}},ln=s("data-lsp",{lsp:"any"},"orr",-1),pn=s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"length")],-1),rn=n(' > 10) return',6),cn=s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),dn=s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"any"},"trim")],-1),_n=n('(0, 10)',5),yn=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),hn=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),un=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"return"),s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),An=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")],-1),Cn={class:"twoslash-annotation right",style:{top:"-0.7rem"}},mn={style:{transform:"translateX(8px) translateY(46px) rotate(190deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Dn=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),gn=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(-3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),bn=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),vn=n(`
    md
    \`\`\`ts twoslash
    +// @errors: 2304
    +// @strict: false
    +
    +function compact(arr) {
    +    if (orr.length > 10) return arr.trim(0, 10)
    +    return arr
    +}
    +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    +\`\`\`
    \`\`\`ts twoslash
    +// @errors: 2304
    +// @strict: false
    +
    +function compact(arr) {
    +    if (orr.length > 10) return arr.trim(0, 10)
    +    return arr
    +}
    +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
    +\`\`\`
    `,1);function Bn(fn,En,Tn,Fn,wn,qn){const r=c,l=d("data-err");return o(),t("div",null,[y,e(r,{readTime:"3",words:"541"}),h,u,A,s("div",C,[m,s("div",D,[s("div",g,[b,v,s("pre",null,[s("code",B,[s("div",f,[s("pre",E,[T,s("div",F,[s("code",null,[w,s("div",q,[x,k,s("span",S,[a(" ("),e(l,null,{default:p(()=>[V]),_:1}),a(".")]),I,P,N,R,M]),L,X,Y,O])])]),a(` +`),s("div",$,[a(` + `),(o(),t("svg",j,[a(` + `),H,a(` +`)])),a(` + `),Q,a(` +`)])]),a(` +`),s("div",J,[s("pre",K,[U,s("div",Z,[s("code",null,[z,s("div",W,[G,ss,s("span",as,[a(" ("),e(l,null,{default:p(()=>[ns]),_:1}),a(".")]),os,ts,es,ls,ps]),rs,cs,is,ds])])]),a(` +`),s("div",_s,[a(` + `),(o(),t("svg",ys,[a(` + `),hs,a(` +`)])),a(` + `),us,a(` +`)])])])]),As]),Cs])]),ms,s("div",Ds,[gs,s("div",bs,[s("div",vs,[Bs,fs,s("pre",null,[s("code",Es,[s("div",Ts,[s("pre",Fs,[ws,s("div",qs,[s("code",null,[xs,s("div",ks,[Ss,Vs,s("span",Is,[a(" ("),e(l,null,{default:p(()=>[Ps]),_:1}),a(".")]),Ns,Rs,Ms,Ls,Xs]),Ys,Os,$s,js])])]),a(` +`),s("div",Hs,[a(` + `),(o(),t("svg",Qs,[a(` + `),Js,a(` +`)])),a(` + `),Ks,a(` +`)])]),a(` +`),s("div",Us,[s("pre",Zs,[zs,s("div",Ws,[s("code",null,[Gs,s("div",sa,[aa,na,s("span",oa,[a(" ("),e(l,null,{default:p(()=>[ta]),_:1}),a(".")]),ea,la,pa,ra,ca]),ia,da,_a,ya])])]),a(` +`),s("div",ha,[a(` + `),(o(),t("svg",ua,[a(` + `),Aa,a(` +`)])),a(` + `),Ca,a(` +`)])])])]),ma]),Da])]),ga,s("div",ba,[va,s("div",Ba,[s("div",fa,[Ea,Ta,s("pre",null,[s("code",Fa,[s("div",wa,[s("pre",qa,[xa,s("div",ka,[s("code",null,[Sa,s("div",Va,[Ia,Pa,s("span",Na,[a(" ("),e(l,null,{default:p(()=>[Ra]),_:1}),a(".")]),Ma,La,Xa,Ya,Oa]),$a,ja,Ha,Qa])])]),a(` +`),s("div",Ja,[a(` + `),(o(),t("svg",Ka,[a(` + `),Ua,a(` +`)])),a(` + `),Za,a(` +`)])]),a(` +`),s("div",za,[s("pre",Wa,[Ga,s("div",sn,[s("code",null,[an,s("div",nn,[on,tn,s("span",en,[a(" ("),e(l,null,{default:p(()=>[ln]),_:1}),a(".")]),pn,rn,cn,dn,_n]),yn,hn,un,An])])]),a(` +`),s("div",Cn,[a(` + `),(o(),t("svg",mn,[a(` + `),Dn,a(` +`)])),a(` + `),gn,a(` +`)])])])]),bn]),vn])])])}const In=i(_,[["render",Bn]]);export{Vn as __pageData,In as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.a42ad2a7.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.a42ad2a7.lean.js new file mode 100644 index 00000000..fa2499d1 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_annotations.md.a42ad2a7.lean.js @@ -0,0 +1,40 @@ +import{_ as c}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as d,o,c as t,H as e,k as s,a,w as p,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const Vn=JSON.parse('{"title":"Meta Annotations","description":"Annotations provide a way to provide outside commentary on your code.","frontmatter":{"description":"Annotations provide a way to provide outside commentary on your code.","title":"Meta Annotations"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/annotations.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/annotations.md","lastUpdated":1699051935000}'),_={name:"application/vitepress-plugin-shiki-twoslash/api/annotations.md"},y=s("h1",{id:"queries",tabindex:"-1"},[a("Queries "),s("a",{class:"header-anchor",href:"#queries","aria-label":'Permalink to "Queries"'},"​")],-1),h=s("p",null,"Sometimes the thing you want to say is about the code, annotations provide a way to provide outside commentary on your code.",-1),u=s("h2",{id:"annotate-left-right-overrides-text",tabindex:"-1"},[s("code",null,"@annotate: [left|right] [overrides] - [text]"),a(),s("a",{class:"header-anchor",href:"#annotate-left-right-overrides-text","aria-label":'Permalink to "`@annotate: [left|right] [overrides] - [text]`"'},"​")],-1),A=s("p",null,"Annotate has a lot more controls than most of the other Twoslash commands, because each use of it probably needs to feel a bit different. Here's an example based on the TypeScript home page, click it to get it running so we can talk about what it does:",-1),C={class:"vp-code-group vp-adaptive-theme"},m=n("",1),D={class:"blocks"},g={class:"language-ts vp-adaptive-theme active line-numbers-mode"},b=s("button",{title:"Copy Code",class:"copy"},null,-1),v=s("span",{class:"lang"},"ts",-1),B={class:"language-ts"},f={class:"tag-container"},E={class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},T=s("div",{class:"language-id"},"ts",-1),F={class:"code-container"},w=s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#ADBAC7"}},") {")],-1),q={class:"line"},x=s("span",{style:{color:"#ADBAC7"}}," ",-1),k=s("span",{style:{color:"#F47067"}},"if",-1),S={style:{color:"#ADBAC7"}},V=s("data-lsp",{lsp:"any"},"orr",-1),I=s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"any"},"length")],-1),P=n("",6),N=s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),R=s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"any"},"trim")],-1),M=n("",5),L=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),X=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),Y=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),O=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")],-1),$={class:"twoslash-annotation left",style:{top:"0rem"}},j={style:{transform:"translateX(8px) translateY(27px) rotate(90deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},H=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),Q=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),J={class:"tag-container"},K={class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},U=s("div",{class:"language-id"},"ts",-1),Z={class:"code-container"},z=s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#24292E"}},") {")],-1),W={class:"line"},G=s("span",{style:{color:"#24292E"}}," ",-1),ss=s("span",{style:{color:"#D73A49"}},"if",-1),as={style:{color:"#24292E"}},ns=s("data-lsp",{lsp:"any"},"orr",-1),os=s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"length")],-1),ts=n("",6),es=s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),ls=s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ps=n("",5),rs=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),cs=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),is=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"return"),s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),ds=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")],-1),_s={class:"twoslash-annotation left",style:{top:"0rem"}},ys={style:{transform:"translateX(8px) translateY(27px) rotate(90deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},hs=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),us=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),As=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),Cs=n("",1),ms=n("",4),Ds={class:"vp-code-group vp-adaptive-theme"},gs=n("",1),bs={class:"blocks"},vs={class:"language-ts vp-adaptive-theme active line-numbers-mode"},Bs=s("button",{title:"Copy Code",class:"copy"},null,-1),fs=s("span",{class:"lang"},"ts",-1),Es={class:"language-ts"},Ts={class:"tag-container"},Fs={class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},ws=s("div",{class:"language-id"},"ts",-1),qs={class:"code-container"},xs=s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#ADBAC7"}},") {")],-1),ks={class:"line"},Ss=s("span",{style:{color:"#ADBAC7"}}," ",-1),Vs=s("span",{style:{color:"#F47067"}},"if",-1),Is={style:{color:"#ADBAC7"}},Ps=s("data-lsp",{lsp:"any"},"orr",-1),Ns=s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"any"},"length")],-1),Rs=n("",6),Ms=s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),Ls=s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"any"},"trim")],-1),Xs=n("",5),Ys=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),Os=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),$s=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),js=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")],-1),Hs={class:"twoslash-annotation right",style:{top:"3rem"}},Qs={style:{transform:"translateX(-10px) translateY(-10px) rotate(-50deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Js=s("path",{d:"M27 39C26.5 32.7511 21.9 17.5173 7.5 6.57333M16.5 4.04L0.999999 0.999998C3.16667 4.88444 7.5 13.16 7.5 15.1867",stroke:"black"},null,-1),Ks=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(0deg)"}},"Discovered a typo, the param is arr, not orr!",-1),Us={class:"tag-container"},Zs={class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},zs=s("div",{class:"language-id"},"ts",-1),Ws={class:"code-container"},Gs=s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#24292E"}},") {")],-1),sa={class:"line"},aa=s("span",{style:{color:"#24292E"}}," ",-1),na=s("span",{style:{color:"#D73A49"}},"if",-1),oa={style:{color:"#24292E"}},ta=s("data-lsp",{lsp:"any"},"orr",-1),ea=s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"length")],-1),la=n("",6),pa=s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),ra=s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"any"},"trim")],-1),ca=n("",5),ia=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),da=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),_a=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"return"),s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),ya=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")],-1),ha={class:"twoslash-annotation right",style:{top:"3rem"}},ua={style:{transform:"translateX(-10px) translateY(-10px) rotate(-50deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Aa=s("path",{d:"M27 39C26.5 32.7511 21.9 17.5173 7.5 6.57333M16.5 4.04L0.999999 0.999998C3.16667 4.88444 7.5 13.16 7.5 15.1867",stroke:"black"},null,-1),Ca=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(0deg)"}},"Discovered a typo, the param is arr, not orr!",-1),ma=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),Da=n("",1),ga=s("p",null,"Upside down arrow pointing at the error, using flipped to re-flip the arrow:",-1),ba={class:"vp-code-group vp-adaptive-theme"},va=n("",1),Ba={class:"blocks"},fa={class:"language-ts vp-adaptive-theme active line-numbers-mode"},Ea=s("button",{title:"Copy Code",class:"copy"},null,-1),Ta=s("span",{class:"lang"},"ts",-1),Fa={class:"language-ts"},wa={class:"tag-container"},qa={class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},xa=s("div",{class:"language-id"},"ts",-1),ka={class:"code-container"},Sa=s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#ADBAC7"}},") {")],-1),Va={class:"line"},Ia=s("span",{style:{color:"#ADBAC7"}}," ",-1),Pa=s("span",{style:{color:"#F47067"}},"if",-1),Na={style:{color:"#ADBAC7"}},Ra=s("data-lsp",{lsp:"any"},"orr",-1),Ma=s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"any"},"length")],-1),La=n("",6),Xa=s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),Ya=s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"any"},"trim")],-1),Oa=n("",5),$a=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),ja=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),Ha=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),Qa=s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")],-1),Ja={class:"twoslash-annotation right",style:{top:"-0.7rem"}},Ka={style:{transform:"translateX(8px) translateY(46px) rotate(190deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Ua=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),Za=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(-3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),za={class:"tag-container"},Wa={class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},Ga=s("div",{class:"language-id"},"ts",-1),sn={class:"code-container"},an=s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function compact(arr: any): any"},"compact")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(parameter) arr: any"},"arr")]),s("span",{style:{color:"#24292E"}},") {")],-1),nn={class:"line"},on=s("span",{style:{color:"#24292E"}}," ",-1),tn=s("span",{style:{color:"#D73A49"}},"if",-1),en={style:{color:"#24292E"}},ln=s("data-lsp",{lsp:"any"},"orr",-1),pn=s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"length")],-1),rn=n("",6),cn=s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr"),a(".")],-1),dn=s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"any"},"trim")],-1),_n=n("",5),yn=s("span",{class:"error"},[s("span",null,"Cannot find name 'orr'."),s("span",{class:"code"},"2304")],-1),hn=s("span",{class:"error-behind"},"Cannot find name 'orr'.",-1),un=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"return"),s("span",{style:{color:"#24292E"}},[a(),s("data-lsp",{lsp:"(parameter) arr: any"},"arr")])],-1),An=s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")],-1),Cn={class:"twoslash-annotation right",style:{top:"-0.7rem"}},mn={style:{transform:"translateX(8px) translateY(46px) rotate(190deg)"},width:"40",height:"40",viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Dn=s("path",{d:"M1 39C1.5 32.7511 6.1 17.5173 20.5 6.57333M11.5 4.04L27 0.999998C24.8333 4.88444 20.5 13.16 20.5 15.1867",stroke:"black"},null,-1),gn=s("p",{class:"twoslash-annotation-text",style:{transform:"rotate(-3deg)"}},"Discovered a typo, the param is arr, not orr!",-1),bn=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),vn=n("",1);function Bn(fn,En,Tn,Fn,wn,qn){const r=c,l=d("data-err");return o(),t("div",null,[y,e(r,{readTime:"3",words:"541"}),h,u,A,s("div",C,[m,s("div",D,[s("div",g,[b,v,s("pre",null,[s("code",B,[s("div",f,[s("pre",E,[T,s("div",F,[s("code",null,[w,s("div",q,[x,k,s("span",S,[a(" ("),e(l,null,{default:p(()=>[V]),_:1}),a(".")]),I,P,N,R,M]),L,X,Y,O])])]),a(` +`),s("div",$,[a(` + `),(o(),t("svg",j,[a(` + `),H,a(` +`)])),a(` + `),Q,a(` +`)])]),a(` +`),s("div",J,[s("pre",K,[U,s("div",Z,[s("code",null,[z,s("div",W,[G,ss,s("span",as,[a(" ("),e(l,null,{default:p(()=>[ns]),_:1}),a(".")]),os,ts,es,ls,ps]),rs,cs,is,ds])])]),a(` +`),s("div",_s,[a(` + `),(o(),t("svg",ys,[a(` + `),hs,a(` +`)])),a(` + `),us,a(` +`)])])])]),As]),Cs])]),ms,s("div",Ds,[gs,s("div",bs,[s("div",vs,[Bs,fs,s("pre",null,[s("code",Es,[s("div",Ts,[s("pre",Fs,[ws,s("div",qs,[s("code",null,[xs,s("div",ks,[Ss,Vs,s("span",Is,[a(" ("),e(l,null,{default:p(()=>[Ps]),_:1}),a(".")]),Ns,Rs,Ms,Ls,Xs]),Ys,Os,$s,js])])]),a(` +`),s("div",Hs,[a(` + `),(o(),t("svg",Qs,[a(` + `),Js,a(` +`)])),a(` + `),Ks,a(` +`)])]),a(` +`),s("div",Us,[s("pre",Zs,[zs,s("div",Ws,[s("code",null,[Gs,s("div",sa,[aa,na,s("span",oa,[a(" ("),e(l,null,{default:p(()=>[ta]),_:1}),a(".")]),ea,la,pa,ra,ca]),ia,da,_a,ya])])]),a(` +`),s("div",ha,[a(` + `),(o(),t("svg",ua,[a(` + `),Aa,a(` +`)])),a(` + `),Ca,a(` +`)])])])]),ma]),Da])]),ga,s("div",ba,[va,s("div",Ba,[s("div",fa,[Ea,Ta,s("pre",null,[s("code",Fa,[s("div",wa,[s("pre",qa,[xa,s("div",ka,[s("code",null,[Sa,s("div",Va,[Ia,Pa,s("span",Na,[a(" ("),e(l,null,{default:p(()=>[Ra]),_:1}),a(".")]),Ma,La,Xa,Ya,Oa]),$a,ja,Ha,Qa])])]),a(` +`),s("div",Ja,[a(` + `),(o(),t("svg",Ka,[a(` + `),Ua,a(` +`)])),a(` + `),Za,a(` +`)])]),a(` +`),s("div",za,[s("pre",Wa,[Ga,s("div",sn,[s("code",null,[an,s("div",nn,[on,tn,s("span",en,[a(" ("),e(l,null,{default:p(()=>[ln]),_:1}),a(".")]),pn,rn,cn,dn,_n]),yn,hn,un,An])])]),a(` +`),s("div",Cn,[a(` + `),(o(),t("svg",mn,[a(` + `),Dn,a(` +`)])),a(` + `),gn,a(` +`)])])])]),bn]),vn])])])}const In=i(_,[["render",Bn]]);export{Vn as __pageData,In as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.2a5fd9c3.js b/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.2a5fd9c3.js new file mode 100644 index 00000000..296adc21 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.2a5fd9c3.js @@ -0,0 +1,45 @@ +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as t,H as c,k as s,a as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const W=JSON.parse('{"title":"Cutting","description":"Remove unnecessary code from your examples.","frontmatter":{"description":"Remove unnecessary code from your examples.","title":"Cutting"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/cutting.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/cutting.md","lastUpdated":1699051935000}'),r={name:"application/vitepress-plugin-shiki-twoslash/api/cutting.md"},p=s("h1",{id:"cutting",tabindex:"-1"},[l("Cutting "),s("a",{class:"header-anchor",href:"#cutting","aria-label":'Permalink to "Cutting"'},"​")],-1),i=s("p",null,"Every Twoslash code example needs to be a complete TypeScript program so it can compile. Quite often to make it compile, there is a bunch of code which isn't relevant to the user. This can be extracted out of the code examples via cut comments.",-1),d=s("h2",{id:"cut",tabindex:"-1"},[s("code",null,"---cut---"),l(),s("a",{class:"header-anchor",href:"#cut","aria-label":'Permalink to "`---cut---`"'},"​")],-1),y=s("p",null,[l("Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the "),s("code",null,"---cut---"),l(".")],-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-Pof92",id:"tab-5hj6UyJ",checked:"checked"}),s("label",{for:"tab-5hj6UyJ"},"output"),s("input",{type:"radio",name:"group-Pof92",id:"tab-NiHW1ms"}),s("label",{for:"tab-NiHW1ms"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#ADBAC7"}},[l("("),s("data-lsp",{lsp:"const level: string"},"level"),l(")")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#24292E"}},[l("("),s("data-lsp",{lsp:"const level: string"},"level"),l(")")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"level"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'Danger'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"console."),s("span",{style:{color:"#DCBDFB"}},"log"),s("span",{style:{color:"#ADBAC7"}},"(level)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"level"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'Danger'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"console."),s("span",{style:{color:"#6F42C1"}},"log"),s("span",{style:{color:"#24292E"}},"(level)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),h=s("p",null,[l("Cutting even works across "),s("a",{href:"./multi-file"},"multiple files"),l(". This is why "),s("code",null,"// @filename: [file]"),l(" is specifically the only Twoslash command which is not removed, because if it's not relevant it can be "),s("code",null,"---cut---"),l(" away.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-wrmVz",id:"tab-2b4PoNy",checked:"checked"}),s("label",{for:"tab-2b4PoNy"},"output"),s("input",{type:"radio",name:"group-wrmVz",id:"tab-qJO2Ms2"}),s("label",{for:"tab-qJO2Ms2"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) const helloWorld: string +import helloWorld`},"helloWorld"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'./a'")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#ADBAC7"}},[l("("),s("data-lsp",{lsp:`(alias) const helloWorld: string +import helloWorld`},"helloWorld"),l(")")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) const helloWorld: string +import helloWorld`},"helloWorld"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'./a'")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#24292E"}},[l("("),s("data-lsp",{lsp:`(alias) const helloWorld: string +import helloWorld`},"helloWorld"),l(")")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: a.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"helloWorld"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'Hi'")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: b.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," { helloWorld } "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'./a'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"console."),s("span",{style:{color:"#DCBDFB"}},"log"),s("span",{style:{color:"#ADBAC7"}},"(helloWorld)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: a.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"helloWorld"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'Hi'")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: b.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," { helloWorld } "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'./a'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"console."),s("span",{style:{color:"#6F42C1"}},"log"),s("span",{style:{color:"#24292E"}},"(helloWorld)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1),b=s("h2",{id:"cut-after",tabindex:"-1"},[s("code",null,"---cut-after---"),l(),s("a",{class:"header-anchor",href:"#cut-after","aria-label":'Permalink to "`---cut-after---`"'},"​")],-1),C=s("p",null,[l("The sibling to "),s("code",null,"---cut---"),l(", which trims anything after the sigil:")],-1),g=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-K1hzs",id:"tab-XbOFc5e",checked:"checked"}),s("label",{for:"tab-XbOFc5e"},"output"),s("input",{type:"radio",name:"group-K1hzs",id:"tab-V5UQGCJ"}),s("label",{for:"tab-V5UQGCJ"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-tsx vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"tsx"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"tsx"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," <"),s("span",{style:{color:"#8DDB8C"}},[s("data-lsp",{lsp:"any"},"Container")]),s("span",{style:{color:"#ADBAC7"}},">")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," <"),s("span",{style:{color:"#8DDB8C"}},[s("data-lsp",{lsp:"any"},"ImportantComponent")]),s("span",{style:{color:"#ADBAC7"}}," />")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," ")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"tsx"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"Container")]),s("span",{style:{color:"#24292E"}},">")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"ImportantComponent")]),s("span",{style:{color:"#24292E"}}," />")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," ")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```tsx twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"Page"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#ADBAC7"}}," (")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," <"),s("span",{style:{color:"#8DDB8C"}},"Container"),s("span",{style:{color:"#ADBAC7"}},">")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," <"),s("span",{style:{color:"#8DDB8C"}},"ImportantComponent"),s("span",{style:{color:"#ADBAC7"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," ")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ---cut-after---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```tsx twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"Page"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," (")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#005CC5"}},"Container"),s("span",{style:{color:"#24292E"}},">")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#005CC5"}},"ImportantComponent"),s("span",{style:{color:"#24292E"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," ")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// ---cut-after---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1);function A(v,D,B,f,k,E){const a=e;return n(),t("div",null,[p,c(a,{readTime:"1",words:"242"}),i,d,y,u,h,m,b,C,g])}const x=o(r,[["render",A]]);export{W as __pageData,x as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.2a5fd9c3.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.2a5fd9c3.lean.js new file mode 100644 index 00000000..296adc21 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.2a5fd9c3.lean.js @@ -0,0 +1,45 @@ +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as t,H as c,k as s,a as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const W=JSON.parse('{"title":"Cutting","description":"Remove unnecessary code from your examples.","frontmatter":{"description":"Remove unnecessary code from your examples.","title":"Cutting"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/cutting.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/cutting.md","lastUpdated":1699051935000}'),r={name:"application/vitepress-plugin-shiki-twoslash/api/cutting.md"},p=s("h1",{id:"cutting",tabindex:"-1"},[l("Cutting "),s("a",{class:"header-anchor",href:"#cutting","aria-label":'Permalink to "Cutting"'},"​")],-1),i=s("p",null,"Every Twoslash code example needs to be a complete TypeScript program so it can compile. Quite often to make it compile, there is a bunch of code which isn't relevant to the user. This can be extracted out of the code examples via cut comments.",-1),d=s("h2",{id:"cut",tabindex:"-1"},[s("code",null,"---cut---"),l(),s("a",{class:"header-anchor",href:"#cut","aria-label":'Permalink to "`---cut---`"'},"​")],-1),y=s("p",null,[l("Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the "),s("code",null,"---cut---"),l(".")],-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-Pof92",id:"tab-5hj6UyJ",checked:"checked"}),s("label",{for:"tab-5hj6UyJ"},"output"),s("input",{type:"radio",name:"group-Pof92",id:"tab-NiHW1ms"}),s("label",{for:"tab-NiHW1ms"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#ADBAC7"}},[l("("),s("data-lsp",{lsp:"const level: string"},"level"),l(")")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#24292E"}},[l("("),s("data-lsp",{lsp:"const level: string"},"level"),l(")")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"level"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'Danger'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"console."),s("span",{style:{color:"#DCBDFB"}},"log"),s("span",{style:{color:"#ADBAC7"}},"(level)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"level"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'Danger'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"console."),s("span",{style:{color:"#6F42C1"}},"log"),s("span",{style:{color:"#24292E"}},"(level)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),h=s("p",null,[l("Cutting even works across "),s("a",{href:"./multi-file"},"multiple files"),l(". This is why "),s("code",null,"// @filename: [file]"),l(" is specifically the only Twoslash command which is not removed, because if it's not relevant it can be "),s("code",null,"---cut---"),l(" away.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-wrmVz",id:"tab-2b4PoNy",checked:"checked"}),s("label",{for:"tab-2b4PoNy"},"output"),s("input",{type:"radio",name:"group-wrmVz",id:"tab-qJO2Ms2"}),s("label",{for:"tab-qJO2Ms2"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) const helloWorld: string +import helloWorld`},"helloWorld"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'./a'")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#ADBAC7"}},[l("("),s("data-lsp",{lsp:`(alias) const helloWorld: string +import helloWorld`},"helloWorld"),l(")")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) const helloWorld: string +import helloWorld`},"helloWorld"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'./a'")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#24292E"}},[l("("),s("data-lsp",{lsp:`(alias) const helloWorld: string +import helloWorld`},"helloWorld"),l(")")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: a.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"helloWorld"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'Hi'")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: b.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," { helloWorld } "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'./a'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"console."),s("span",{style:{color:"#DCBDFB"}},"log"),s("span",{style:{color:"#ADBAC7"}},"(helloWorld)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: a.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"helloWorld"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'Hi'")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: b.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," { helloWorld } "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'./a'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"console."),s("span",{style:{color:"#6F42C1"}},"log"),s("span",{style:{color:"#24292E"}},"(helloWorld)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1),b=s("h2",{id:"cut-after",tabindex:"-1"},[s("code",null,"---cut-after---"),l(),s("a",{class:"header-anchor",href:"#cut-after","aria-label":'Permalink to "`---cut-after---`"'},"​")],-1),C=s("p",null,[l("The sibling to "),s("code",null,"---cut---"),l(", which trims anything after the sigil:")],-1),g=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-K1hzs",id:"tab-XbOFc5e",checked:"checked"}),s("label",{for:"tab-XbOFc5e"},"output"),s("input",{type:"radio",name:"group-K1hzs",id:"tab-V5UQGCJ"}),s("label",{for:"tab-V5UQGCJ"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-tsx vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"tsx"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"tsx"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," <"),s("span",{style:{color:"#8DDB8C"}},[s("data-lsp",{lsp:"any"},"Container")]),s("span",{style:{color:"#ADBAC7"}},">")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," <"),s("span",{style:{color:"#8DDB8C"}},[s("data-lsp",{lsp:"any"},"ImportantComponent")]),s("span",{style:{color:"#ADBAC7"}}," />")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," ")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"tsx"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"Container")]),s("span",{style:{color:"#24292E"}},">")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"any"},"ImportantComponent")]),s("span",{style:{color:"#24292E"}}," />")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," ")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```tsx twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"Page"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#ADBAC7"}}," (")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," <"),s("span",{style:{color:"#8DDB8C"}},"Container"),s("span",{style:{color:"#ADBAC7"}},">")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," <"),s("span",{style:{color:"#8DDB8C"}},"ImportantComponent"),s("span",{style:{color:"#ADBAC7"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," ")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ---cut-after---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```tsx twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"Page"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," (")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#005CC5"}},"Container"),s("span",{style:{color:"#24292E"}},">")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#005CC5"}},"ImportantComponent"),s("span",{style:{color:"#24292E"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," ")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// ---cut-after---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1);function A(v,D,B,f,k,E){const a=e;return n(),t("div",null,[p,c(a,{readTime:"1",words:"242"}),i,d,y,u,h,m,b,C,g])}const x=o(r,[["render",A]]);export{W as __pageData,x as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.b6b7a28c.js b/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.b6b7a28c.js deleted file mode 100644 index 7bf92c8b..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.b6b7a28c.js +++ /dev/null @@ -1,45 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as n,c as t,H as c,k as s,a as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const W=JSON.parse('{"title":"Cutting","description":"Remove unnecessary code from your examples.","frontmatter":{"description":"Remove unnecessary code from your examples.","title":"Cutting"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/cutting.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/cutting.md","lastUpdated":1695377563000}'),r={name:"application/vitepress-plugin-shiki-twoslash/api/cutting.md"},p=s("h1",{id:"cutting",tabindex:"-1"},[l("Cutting "),s("a",{class:"header-anchor",href:"#cutting","aria-label":'Permalink to "Cutting"'},"​")],-1),i=s("p",null,"Every Twoslash code example needs to be a complete TypeScript program so it can compile. Quite often to make it compile, there is a bunch of code which isn't relevant to the user. This can be extracted out of the code examples via cut comments.",-1),d=s("h2",{id:"cut",tabindex:"-1"},[s("code",null,"---cut---"),l(),s("a",{class:"header-anchor",href:"#cut","aria-label":'Permalink to "`---cut---`"'},"​")],-1),y=s("p",null,[l("Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the "),s("code",null,"---cut---"),l(".")],-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group--m9c0",id:"tab-KXdVKaA",checked:"checked"}),s("label",{for:"tab-KXdVKaA"},"output"),s("input",{type:"radio",name:"group--m9c0",id:"tab-M6jk-aB"}),s("label",{for:"tab-M6jk-aB"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const level: string"},"level")]),s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const level: string"},"level")]),s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"level"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'Danger'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},"level"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"level"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'Danger'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},"level"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),h=s("p",null,[l("Cutting even works across "),s("a",{href:"./multi-file"},"multiple files"),l(". This is why "),s("code",null,"// @filename: [file]"),l(" is specifically the only Twoslash command which is not removed, because if it's not relevant it can be "),s("code",null,"---cut---"),l(" away.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-9cL3d",id:"tab-Mjx7nhA",checked:"checked"}),s("label",{for:"tab-Mjx7nhA"},"output"),s("input",{type:"radio",name:"group-9cL3d",id:"tab-Yzin58W"}),s("label",{for:"tab-Yzin58W"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const helloWorld: string -import helloWorld`},"helloWorld")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'./a'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const helloWorld: string -import helloWorld`},"helloWorld")]),s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const helloWorld: string -import helloWorld`},"helloWorld")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'./a'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const helloWorld: string -import helloWorld`},"helloWorld")]),s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: a.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'Hi'")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: b.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'./a'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: a.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'Hi'")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: b.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'./a'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1),b=s("h2",{id:"cut-after",tabindex:"-1"},[s("code",null,"---cut-after---"),l(),s("a",{class:"header-anchor",href:"#cut-after","aria-label":'Permalink to "`---cut-after---`"'},"​")],-1),g=s("p",null,[l("The sibling to "),s("code",null,"---cut---"),l(", which trims anything after the sigil:")],-1),v=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-JpNOZ",id:"tab-Dp82oAb",checked:"checked"}),s("label",{for:"tab-Dp82oAb"},"output"),s("input",{type:"radio",name:"group-JpNOZ",id:"tab-MPwaQQv"}),s("label",{for:"tab-MPwaQQv"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-tsx vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"tsx"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"tsx"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"<"),s("span",{style:{color:"#859900"}},[s("data-lsp",{lsp:"any"},"Container")]),s("span",{style:{color:"#586E75"}},">")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"<"),s("span",{style:{color:"#859900"}},[s("data-lsp",{lsp:"any"},"ImportantComponent")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"/>")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"tsx"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"<"),s("span",{style:{color:"#859900"}},[s("data-lsp",{lsp:"any"},"Container")]),s("span",{style:{color:"#93A1A1"}},">")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"<"),s("span",{style:{color:"#859900"}},[s("data-lsp",{lsp:"any"},"ImportantComponent")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"/>")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```tsx twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"Page"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," () "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"=>"),s("span",{style:{color:"#839496"}}," (")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"<"),s("span",{style:{color:"#859900"}},"Container"),s("span",{style:{color:"#586E75"}},">")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"<"),s("span",{style:{color:"#859900"}},"ImportantComponent"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"/>")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut-after---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```tsx twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"Page"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," () "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"=>"),s("span",{style:{color:"#657B83"}}," (")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"<"),s("span",{style:{color:"#859900"}},"Container"),s("span",{style:{color:"#93A1A1"}},">")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"<"),s("span",{style:{color:"#859900"}},"ImportantComponent"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"/>")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut-after---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1);function B(f,A,k,w,D,C){const o=a;return n(),t("div",null,[p,c(o,{readTime:"1",words:"242"}),i,d,y,u,h,m,b,g,v])}const z=e(r,[["render",B]]);export{W as __pageData,z as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.b6b7a28c.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.b6b7a28c.lean.js deleted file mode 100644 index 7bf92c8b..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_cutting.md.b6b7a28c.lean.js +++ /dev/null @@ -1,45 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as n,c as t,H as c,k as s,a as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const W=JSON.parse('{"title":"Cutting","description":"Remove unnecessary code from your examples.","frontmatter":{"description":"Remove unnecessary code from your examples.","title":"Cutting"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/cutting.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/cutting.md","lastUpdated":1695377563000}'),r={name:"application/vitepress-plugin-shiki-twoslash/api/cutting.md"},p=s("h1",{id:"cutting",tabindex:"-1"},[l("Cutting "),s("a",{class:"header-anchor",href:"#cutting","aria-label":'Permalink to "Cutting"'},"​")],-1),i=s("p",null,"Every Twoslash code example needs to be a complete TypeScript program so it can compile. Quite often to make it compile, there is a bunch of code which isn't relevant to the user. This can be extracted out of the code examples via cut comments.",-1),d=s("h2",{id:"cut",tabindex:"-1"},[s("code",null,"---cut---"),l(),s("a",{class:"header-anchor",href:"#cut","aria-label":'Permalink to "`---cut---`"'},"​")],-1),y=s("p",null,[l("Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the "),s("code",null,"---cut---"),l(".")],-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group--m9c0",id:"tab-KXdVKaA",checked:"checked"}),s("label",{for:"tab-KXdVKaA"},"output"),s("input",{type:"radio",name:"group--m9c0",id:"tab-M6jk-aB"}),s("label",{for:"tab-M6jk-aB"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const level: string"},"level")]),s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const level: string"},"level")]),s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"level"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'Danger'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},"level"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"level"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'Danger'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},"level"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),h=s("p",null,[l("Cutting even works across "),s("a",{href:"./multi-file"},"multiple files"),l(". This is why "),s("code",null,"// @filename: [file]"),l(" is specifically the only Twoslash command which is not removed, because if it's not relevant it can be "),s("code",null,"---cut---"),l(" away.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-9cL3d",id:"tab-Mjx7nhA",checked:"checked"}),s("label",{for:"tab-Mjx7nhA"},"output"),s("input",{type:"radio",name:"group-9cL3d",id:"tab-Yzin58W"}),s("label",{for:"tab-Yzin58W"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const helloWorld: string -import helloWorld`},"helloWorld")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'./a'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const helloWorld: string -import helloWorld`},"helloWorld")]),s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const helloWorld: string -import helloWorld`},"helloWorld")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'./a'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const helloWorld: string -import helloWorld`},"helloWorld")]),s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: a.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'Hi'")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: b.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'./a'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: a.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'Hi'")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: b.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'./a'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},"helloWorld"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1),b=s("h2",{id:"cut-after",tabindex:"-1"},[s("code",null,"---cut-after---"),l(),s("a",{class:"header-anchor",href:"#cut-after","aria-label":'Permalink to "`---cut-after---`"'},"​")],-1),g=s("p",null,[l("The sibling to "),s("code",null,"---cut---"),l(", which trims anything after the sigil:")],-1),v=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-JpNOZ",id:"tab-Dp82oAb",checked:"checked"}),s("label",{for:"tab-Dp82oAb"},"output"),s("input",{type:"radio",name:"group-JpNOZ",id:"tab-MPwaQQv"}),s("label",{for:"tab-MPwaQQv"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-tsx vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"tsx"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"tsx"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"<"),s("span",{style:{color:"#859900"}},[s("data-lsp",{lsp:"any"},"Container")]),s("span",{style:{color:"#586E75"}},">")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"<"),s("span",{style:{color:"#859900"}},[s("data-lsp",{lsp:"any"},"ImportantComponent")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"/>")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"tsx"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"<"),s("span",{style:{color:"#859900"}},[s("data-lsp",{lsp:"any"},"Container")]),s("span",{style:{color:"#93A1A1"}},">")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"<"),s("span",{style:{color:"#859900"}},[s("data-lsp",{lsp:"any"},"ImportantComponent")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"/>")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```tsx twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"Page"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," () "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"=>"),s("span",{style:{color:"#839496"}}," (")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"<"),s("span",{style:{color:"#859900"}},"Container"),s("span",{style:{color:"#586E75"}},">")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"<"),s("span",{style:{color:"#859900"}},"ImportantComponent"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"/>")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut-after---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```tsx twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"Page"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," () "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"=>"),s("span",{style:{color:"#657B83"}}," (")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"<"),s("span",{style:{color:"#859900"}},"Container"),s("span",{style:{color:"#93A1A1"}},">")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"<"),s("span",{style:{color:"#859900"}},"ImportantComponent"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"/>")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut-after---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1);function B(f,A,k,w,D,C){const o=a;return n(),t("div",null,[p,c(o,{readTime:"1",words:"242"}),i,d,y,u,h,m,b,g,v])}const z=e(r,[["render",B]]);export{W as __pageData,z as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.07068d46.js b/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.07068d46.js new file mode 100644 index 00000000..e47d013f --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.07068d46.js @@ -0,0 +1 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o,c as e,H as p,k as s,a as t,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Emit","description":"You can replace the contents of your code examples with the results of running TypeScript over the project.","frontmatter":{"description":"You can replace the contents of your code examples with the results of running TypeScript over the project.","title":"Emit"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/emit.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/emit.md","lastUpdated":1699051935000}'),r={name:"application/vitepress-plugin-shiki-twoslash/api/emit.md"},i=s("h1",{id:"emit",tabindex:"-1"},[t("Emit "),s("a",{class:"header-anchor",href:"#emit","aria-label":'Permalink to "Emit"'},"​")],-1),d=c('

    Running a Twoslash code example is a full TypeScript compiler run that will create files inside the virtual file system. You can replace the contents of your code examples with the results of running TypeScript over the project.

    @showEmit

    // @showEmit is the main command to tell Shiki Twoslash that you want to replace the output of your code example with the equivalent .js file.

    ts
    ts
    "use strict";
    const level = 'Danger';
     
    ts
    "use strict";
    const level = 'Danger';
     
    md
    ```ts twoslash\n// @showEmit\nconst level: string = 'Danger'\n```
    ```ts twoslash\n// @showEmit\nconst level: string = 'Danger'\n```

    @showEmittedFile: [file]

    While the .js file is probably the most useful file out of the box, TypeScript does emit other files if you have the right flags enabled (.d.ts and .map) but also when you have a multi-file code sample — you might need to tell Twoslash which file to show. For all these cases you can also add @showEmittedFile: [file] to tell Twoslash which file you want to show.

    Shows emitted .d.ts for a TypeScript code example:

    md
    ```ts twoslash\n// @declaration\n// @showEmit\n// @showEmittedFile: index.d.ts\nexport const hello = 'world'\n```
    ```ts twoslash\n// @declaration\n// @showEmit\n// @showEmittedFile: index.d.ts\nexport const hello = 'world'\n```
    ts
    ts
    export declare const hello = "world";
     
    ts
    export declare const hello = "world";
     

    Shows emitted .map files:

    md
    ```ts twoslash\n// @sourceMap\n// @showEmit\n// @showEmittedFile: index.js.map\nexport const hello = 'world'\n```
    ```ts twoslash\n// @sourceMap\n// @showEmit\n// @showEmittedFile: index.js.map\nexport const hello = 'world'\n```
    ts
    ts
    {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
    ts
    {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
    md
    ```ts twoslash\n// @declaration\n// @declarationMap\n// @showEmit\n// @showEmittedFile: index.d.ts.map\nexport const hello = 'world'\n```
    ```ts twoslash\n// @declaration\n// @declarationMap\n// @showEmit\n// @showEmittedFile: index.d.ts.map\nexport const hello = 'world'\n```
    ts
    ts
    {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
    ts
    {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
    ',11);function y(u,A,h,m,v,b){const a=n;return o(),e("div",null,[i,p(a,{readTime:"1",words:"264"}),d])}const q=l(r,[["render",y]]);export{C as __pageData,q as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.8d757f81.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.07068d46.lean.js similarity index 59% rename from assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.8d757f81.lean.js rename to assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.07068d46.lean.js index 6b3d0f8d..50ffbcff 100644 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.8d757f81.lean.js +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.07068d46.lean.js @@ -1 +1 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o,c as e,H as p,k as s,a as t,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"Emit","description":"You can replace the contents of your code examples with the results of running TypeScript over the project.","frontmatter":{"description":"You can replace the contents of your code examples with the results of running TypeScript over the project.","title":"Emit"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/emit.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/emit.md","lastUpdated":1695377563000}'),r={name:"application/vitepress-plugin-shiki-twoslash/api/emit.md"},i=s("h1",{id:"emit",tabindex:"-1"},[t("Emit "),s("a",{class:"header-anchor",href:"#emit","aria-label":'Permalink to "Emit"'},"​")],-1),d=c("",11);function y(u,A,h,v,m,b){const a=l;return o(),e("div",null,[i,p(a,{readTime:"1",words:"264"}),d])}const B=n(r,[["render",y]]);export{w as __pageData,B as default}; +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o,c as e,H as p,k as s,a as t,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Emit","description":"You can replace the contents of your code examples with the results of running TypeScript over the project.","frontmatter":{"description":"You can replace the contents of your code examples with the results of running TypeScript over the project.","title":"Emit"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/emit.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/emit.md","lastUpdated":1699051935000}'),r={name:"application/vitepress-plugin-shiki-twoslash/api/emit.md"},i=s("h1",{id:"emit",tabindex:"-1"},[t("Emit "),s("a",{class:"header-anchor",href:"#emit","aria-label":'Permalink to "Emit"'},"​")],-1),d=c("",11);function y(u,A,h,m,v,b){const a=n;return o(),e("div",null,[i,p(a,{readTime:"1",words:"264"}),d])}const q=l(r,[["render",y]]);export{C as __pageData,q as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.8d757f81.js b/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.8d757f81.js deleted file mode 100644 index 472e86d4..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_emit.md.8d757f81.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o,c as e,H as p,k as s,a as t,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"Emit","description":"You can replace the contents of your code examples with the results of running TypeScript over the project.","frontmatter":{"description":"You can replace the contents of your code examples with the results of running TypeScript over the project.","title":"Emit"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/emit.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/emit.md","lastUpdated":1695377563000}'),r={name:"application/vitepress-plugin-shiki-twoslash/api/emit.md"},i=s("h1",{id:"emit",tabindex:"-1"},[t("Emit "),s("a",{class:"header-anchor",href:"#emit","aria-label":'Permalink to "Emit"'},"​")],-1),d=c('

    Running a Twoslash code example is a full TypeScript compiler run that will create files inside the virtual file system. You can replace the contents of your code examples with the results of running TypeScript over the project.

    @showEmit

    // @showEmit is the main command to tell Shiki Twoslash that you want to replace the output of your code example with the equivalent .js file.

    ts
    ts
    "use strict";
    const level = 'Danger';
     
    ts
    "use strict";
    const level = 'Danger';
     
    md
    ```ts twoslash\n// @showEmit\nconst level: string = 'Danger'\n```
    ```ts twoslash\n// @showEmit\nconst level: string = 'Danger'\n```

    @showEmittedFile: [file]

    While the .js file is probably the most useful file out of the box, TypeScript does emit other files if you have the right flags enabled (.d.ts and .map) but also when you have a multi-file code sample — you might need to tell Twoslash which file to show. For all these cases you can also add @showEmittedFile: [file] to tell Twoslash which file you want to show.

    Shows emitted .d.ts for a TypeScript code example:

    md
    ```ts twoslash\n// @declaration\n// @showEmit\n// @showEmittedFile: index.d.ts\nexport const hello = 'world'\n```
    ```ts twoslash\n// @declaration\n// @showEmit\n// @showEmittedFile: index.d.ts\nexport const hello = 'world'\n```
    ts
    ts
    export declare const hello = "world";
     
    ts
    export declare const hello = "world";
     

    Shows emitted .map files:

    md
    ```ts twoslash\n// @sourceMap\n// @showEmit\n// @showEmittedFile: index.js.map\nexport const hello = 'world'\n```
    ```ts twoslash\n// @sourceMap\n// @showEmit\n// @showEmittedFile: index.js.map\nexport const hello = 'world'\n```
    ts
    ts
    {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
    ts
    {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
    md
    ```ts twoslash\n// @declaration\n// @declarationMap\n// @showEmit\n// @showEmittedFile: index.d.ts.map\nexport const hello = 'world'\n```
    ```ts twoslash\n// @declaration\n// @declarationMap\n// @showEmit\n// @showEmittedFile: index.d.ts.map\nexport const hello = 'world'\n```
    ts
    ts
    {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
    ts
    {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
    ',11);function y(u,A,h,v,m,b){const a=l;return o(),e("div",null,[i,p(a,{readTime:"1",words:"264"}),d])}const B=n(r,[["render",y]]);export{w as __pageData,B as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.230e0002.js b/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.230e0002.js new file mode 100644 index 00000000..37391ff4 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.230e0002.js @@ -0,0 +1,9 @@ +import{_ as r}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as c,C as p,o as i,c as d,H as o,k as s,w as l,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const is=JSON.parse('{"title":"Errors","description":"Raise compiler errors in your code examples to show incorrect states.","frontmatter":{"description":"Raise compiler errors in your code examples to show incorrect states.","title":"Errors"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/errors.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/errors.md","lastUpdated":1699051935000}'),h={name:"application/vitepress-plugin-shiki-twoslash/api/errors.md"},y=s("h1",{id:"errors",tabindex:"-1"},[a("Errors "),s("a",{class:"header-anchor",href:"#errors","aria-label":'Permalink to "Errors"'},"​")],-1),u=s("p",null,"Most of the time, you want to avoid errors in your code examples. Strictly speaking, this usually means setting the right compiler flags and environment in each code example.",-1),_=s("p",null,"Sometimes however, you do want to raise a compiler error — to show incorrect states. In those cases, twoslash has a way to mark the compiler errors you expect.",-1),m=s("h2",{id:"errors-num",tabindex:"-1"},[s("code",null,"@errors: [num]"),a(),s("a",{class:"header-anchor",href:"#errors-num","aria-label":'Permalink to "`@errors: [num]`"'},"​")],-1),b=s("p",null,"All TypeScript compiler errors have a number, this number is relatively arbitrary and can change between TypeScript versions. For our case these numbers are useul in declaring what we expect to see.",-1),A=s("p",null,[a("You can use "),s("code",null,"// @errors: [num]"),a(" to tell Twoslash that you expect this error to occur. This moves the compiler error message into the code example.")],-1),v={class:"vp-code-group vp-adaptive-theme"},C=n('
    ',1),g={class:"blocks"},D={class:"language-ts vp-adaptive-theme active line-numbers-mode"},k=s("button",{title:"Copy Code",class:"copy"},null,-1),F=s("span",{class:"lang"},"ts",-1),w={class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},E=s("div",{class:"language-id"},"ts",-1),B={class:"code-container"},f=s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'123'")],-1),T={class:"line"},x={style:{color:"#ADBAC7"}},S=s("data-lsp",{lsp:"const a: any"},"a",-1),P=s("span",{style:{color:"#F47067"}},"=",-1),R=s("span",{style:{color:"#ADBAC7"}}," ",-1),V=s("span",{style:{color:"#6CB6FF"}},"132",-1),N=s("span",{class:"error"},[s("span",null,"Cannot assign to 'a' because it is a constant."),s("span",{class:"code"},"2588")],-1),I=s("span",{class:"error-behind"},"Cannot assign to 'a' because it is a constant.",-1),Y={class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},$=s("div",{class:"language-id"},"ts",-1),z={class:"code-container"},X=s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'123'")],-1),j={class:"line"},q={style:{color:"#24292E"}},J=s("data-lsp",{lsp:"const a: any"},"a",-1),Q=s("span",{style:{color:"#D73A49"}},"=",-1),U=s("span",{style:{color:"#24292E"}}," ",-1),L=s("span",{style:{color:"#005CC5"}},"132",-1),Z=s("span",{class:"error"},[s("span",null,"Cannot assign to 'a' because it is a constant."),s("span",{class:"code"},"2588")],-1),H=s("span",{class:"error-behind"},"Cannot assign to 'a' because it is a constant.",-1),M=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),O=n('
    md
    ```ts twoslash\n// @errors: 2588\nconst a = '123'\na = 132\n```
    ```ts twoslash\n// @errors: 2588\nconst a = '123'\na = 132\n```
    ',1),G=s("h2",{id:"noerrors",tabindex:"-1"},[s("code",null,"@noErrors"),a(),s("a",{class:"header-anchor",href:"#noerrors","aria-label":'Permalink to "`@noErrors`"'},"​")],-1),K=s("p",null,[a("Sometimes you have needs in which a broken TypeScript build is okay. A good example of this is using a "),s("a",{href:"./queries#completions"},"completion query"),a(", which requires a broken TypeScript project to work. You can use "),s("code",null,"// @noErrors"),a(" to supress all errors in a code sample, and not have them show inline.")],-1),W=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-QgAzA",id:"tab-LjhXkvo",checked:"checked"}),s("label",{for:"tab-LjhXkvo"},"output"),s("input",{type:"radio",name:"group-QgAzA",id:"tab-pY2ZJR8"}),s("label",{for:"tab-pY2ZJR8"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'123'")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"const a: any"},"a"),a()]),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"132")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'123'")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"const a: any"},"a"),a()]),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"132")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @noErrors")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"a"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'123'")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"a "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"132")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @noErrors")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"a"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'123'")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"a "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"132")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1);function ss(as,os,es,ls,ns,ts){const t=r,e=p("data-err");return i(),d("div",null,[y,o(t,{readTime:"1",words:"227"}),u,_,m,b,A,s("div",v,[C,s("div",g,[s("div",D,[k,F,s("pre",w,[E,s("div",B,[s("code",null,[f,s("div",T,[s("span",x,[o(e,null,{default:l(()=>[S]),_:1}),a()]),P,R,V]),N,I])])]),s("pre",Y,[$,s("div",z,[s("code",null,[X,s("div",j,[s("span",q,[o(e,null,{default:l(()=>[J]),_:1}),a()]),Q,U,L]),Z,H])])]),M]),O])]),G,K,W])}const ds=c(h,[["render",ss]]);export{is as __pageData,ds as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.230e0002.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.230e0002.lean.js new file mode 100644 index 00000000..35cc30cb --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.230e0002.lean.js @@ -0,0 +1,9 @@ +import{_ as r}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as c,C as p,o as i,c as d,H as o,k as s,w as l,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const is=JSON.parse('{"title":"Errors","description":"Raise compiler errors in your code examples to show incorrect states.","frontmatter":{"description":"Raise compiler errors in your code examples to show incorrect states.","title":"Errors"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/errors.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/errors.md","lastUpdated":1699051935000}'),h={name:"application/vitepress-plugin-shiki-twoslash/api/errors.md"},y=s("h1",{id:"errors",tabindex:"-1"},[a("Errors "),s("a",{class:"header-anchor",href:"#errors","aria-label":'Permalink to "Errors"'},"​")],-1),u=s("p",null,"Most of the time, you want to avoid errors in your code examples. Strictly speaking, this usually means setting the right compiler flags and environment in each code example.",-1),_=s("p",null,"Sometimes however, you do want to raise a compiler error — to show incorrect states. In those cases, twoslash has a way to mark the compiler errors you expect.",-1),m=s("h2",{id:"errors-num",tabindex:"-1"},[s("code",null,"@errors: [num]"),a(),s("a",{class:"header-anchor",href:"#errors-num","aria-label":'Permalink to "`@errors: [num]`"'},"​")],-1),b=s("p",null,"All TypeScript compiler errors have a number, this number is relatively arbitrary and can change between TypeScript versions. For our case these numbers are useul in declaring what we expect to see.",-1),A=s("p",null,[a("You can use "),s("code",null,"// @errors: [num]"),a(" to tell Twoslash that you expect this error to occur. This moves the compiler error message into the code example.")],-1),v={class:"vp-code-group vp-adaptive-theme"},C=n("",1),g={class:"blocks"},D={class:"language-ts vp-adaptive-theme active line-numbers-mode"},k=s("button",{title:"Copy Code",class:"copy"},null,-1),F=s("span",{class:"lang"},"ts",-1),w={class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},E=s("div",{class:"language-id"},"ts",-1),B={class:"code-container"},f=s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'123'")],-1),T={class:"line"},x={style:{color:"#ADBAC7"}},S=s("data-lsp",{lsp:"const a: any"},"a",-1),P=s("span",{style:{color:"#F47067"}},"=",-1),R=s("span",{style:{color:"#ADBAC7"}}," ",-1),V=s("span",{style:{color:"#6CB6FF"}},"132",-1),N=s("span",{class:"error"},[s("span",null,"Cannot assign to 'a' because it is a constant."),s("span",{class:"code"},"2588")],-1),I=s("span",{class:"error-behind"},"Cannot assign to 'a' because it is a constant.",-1),Y={class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},$=s("div",{class:"language-id"},"ts",-1),z={class:"code-container"},X=s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'123'")],-1),j={class:"line"},q={style:{color:"#24292E"}},J=s("data-lsp",{lsp:"const a: any"},"a",-1),Q=s("span",{style:{color:"#D73A49"}},"=",-1),U=s("span",{style:{color:"#24292E"}}," ",-1),L=s("span",{style:{color:"#005CC5"}},"132",-1),Z=s("span",{class:"error"},[s("span",null,"Cannot assign to 'a' because it is a constant."),s("span",{class:"code"},"2588")],-1),H=s("span",{class:"error-behind"},"Cannot assign to 'a' because it is a constant.",-1),M=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),O=n("",1),G=s("h2",{id:"noerrors",tabindex:"-1"},[s("code",null,"@noErrors"),a(),s("a",{class:"header-anchor",href:"#noerrors","aria-label":'Permalink to "`@noErrors`"'},"​")],-1),K=s("p",null,[a("Sometimes you have needs in which a broken TypeScript build is okay. A good example of this is using a "),s("a",{href:"./queries#completions"},"completion query"),a(", which requires a broken TypeScript project to work. You can use "),s("code",null,"// @noErrors"),a(" to supress all errors in a code sample, and not have them show inline.")],-1),W=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-QgAzA",id:"tab-LjhXkvo",checked:"checked"}),s("label",{for:"tab-LjhXkvo"},"output"),s("input",{type:"radio",name:"group-QgAzA",id:"tab-pY2ZJR8"}),s("label",{for:"tab-pY2ZJR8"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'123'")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"const a: any"},"a"),a()]),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"132")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'123'")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"const a: any"},"a"),a()]),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"132")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @noErrors")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"a"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'123'")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"a "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"132")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @noErrors")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"a"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'123'")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"a "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"132")]),a(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1);function ss(as,os,es,ls,ns,ts){const t=r,e=p("data-err");return i(),d("div",null,[y,o(t,{readTime:"1",words:"227"}),u,_,m,b,A,s("div",v,[C,s("div",g,[s("div",D,[k,F,s("pre",w,[E,s("div",B,[s("code",null,[f,s("div",T,[s("span",x,[o(e,null,{default:l(()=>[S]),_:1}),a()]),P,R,V]),N,I])])]),s("pre",Y,[$,s("div",z,[s("code",null,[X,s("div",j,[s("span",q,[o(e,null,{default:l(()=>[J]),_:1}),a()]),Q,U,L]),Z,H])])]),M]),O])]),G,K,W])}const ds=c(h,[["render",ss]]);export{is as __pageData,ds as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.8032d46f.js b/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.8032d46f.js deleted file mode 100644 index 22f13961..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.8032d46f.js +++ /dev/null @@ -1,9 +0,0 @@ -import{_ as r}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as c,C as p,o as i,c as d,H as a,k as s,w as l,a as o,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const ys=JSON.parse('{"title":"Errors","description":"Raise compiler errors in your code examples to show incorrect states.","frontmatter":{"description":"Raise compiler errors in your code examples to show incorrect states.","title":"Errors"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/errors.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/errors.md","lastUpdated":1695377563000}'),y={name:"application/vitepress-plugin-shiki-twoslash/api/errors.md"},h=s("h1",{id:"errors",tabindex:"-1"},[o("Errors "),s("a",{class:"header-anchor",href:"#errors","aria-label":'Permalink to "Errors"'},"​")],-1),_=s("p",null,"Most of the time, you want to avoid errors in your code examples. Strictly speaking, this usually means setting the right compiler flags and environment in each code example.",-1),u=s("p",null,"Sometimes however, you do want to raise a compiler error — to show incorrect states. In those cases, twoslash has a way to mark the compiler errors you expect.",-1),m=s("h2",{id:"errors-num",tabindex:"-1"},[s("code",null,"@errors: [num]"),o(),s("a",{class:"header-anchor",href:"#errors-num","aria-label":'Permalink to "`@errors: [num]`"'},"​")],-1),b=s("p",null,"All TypeScript compiler errors have a number, this number is relatively arbitrary and can change between TypeScript versions. For our case these numbers are useul in declaring what we expect to see.",-1),v=s("p",null,[o("You can use "),s("code",null,"// @errors: [num]"),o(" to tell Twoslash that you expect this error to occur. This moves the compiler error message into the code example.")],-1),g={class:"vp-code-group vp-adaptive-theme"},B=n('
    ',1),k={class:"blocks"},w={class:"language-ts vp-adaptive-theme active line-numbers-mode"},f=s("button",{title:"Copy Code",class:"copy"},null,-1),A=s("span",{class:"lang"},"ts",-1),D={class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},E=s("div",{class:"language-id"},"ts",-1),T={class:"code-container"},C=s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")],-1),x={class:"line"},S={style:{color:"#268BD2"}},P=s("data-lsp",{lsp:"const a: any"},"a",-1),z=s("span",{style:{color:"#839496"}}," ",-1),V=s("span",{style:{color:"#859900"}},"=",-1),I=s("span",{style:{color:"#839496"}}," ",-1),N=s("span",{style:{color:"#D33682"}},"132",-1),q=s("span",{class:"error"},[s("span",null,"Cannot assign to 'a' because it is a constant."),s("span",{class:"code"},"2588")],-1),F=s("span",{class:"error-behind"},"Cannot assign to 'a' because it is a constant.",-1),O={class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},$=s("div",{class:"language-id"},"ts",-1),R={class:"code-container"},Y=s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")],-1),j={class:"line"},J={style:{color:"#268BD2"}},G=s("data-lsp",{lsp:"const a: any"},"a",-1),K=s("span",{style:{color:"#657B83"}}," ",-1),L=s("span",{style:{color:"#859900"}},"=",-1),W=s("span",{style:{color:"#657B83"}}," ",-1),Z=s("span",{style:{color:"#D33682"}},"132",-1),H=s("span",{class:"error"},[s("span",null,"Cannot assign to 'a' because it is a constant."),s("span",{class:"code"},"2588")],-1),M=s("span",{class:"error-behind"},"Cannot assign to 'a' because it is a constant.",-1),Q=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),U=n('
    md
    ```ts twoslash\n// @errors: 2588\nconst a = '123'\na = 132\n```
    ```ts twoslash\n// @errors: 2588\nconst a = '123'\na = 132\n```
    ',1),X=s("h2",{id:"noerrors",tabindex:"-1"},[s("code",null,"@noErrors"),o(),s("a",{class:"header-anchor",href:"#noerrors","aria-label":'Permalink to "`@noErrors`"'},"​")],-1),ss=s("p",null,[o("Sometimes you have needs in which a broken TypeScript build is okay. A good example of this is using a "),s("a",{href:"./queries#completions"},"completion query"),o(", which requires a broken TypeScript project to work. You can use "),s("code",null,"// @noErrors"),o(" to supress all errors in a code sample, and not have them show inline.")],-1),os=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-1ZJGh",id:"tab-POfuhrh",checked:"checked"}),s("label",{for:"tab-POfuhrh"},"output"),s("input",{type:"radio",name:"group-1ZJGh",id:"tab-_OVEf2b"}),s("label",{for:"tab-_OVEf2b"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const a: any"},"a")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#D33682"}},"132")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const a: any"},"a")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#D33682"}},"132")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @noErrors")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#D33682"}},"132")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @noErrors")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#D33682"}},"132")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1);function as(es,ls,ns,ts,rs,cs){const t=r,e=p("data-err");return i(),d("div",null,[h,a(t,{readTime:"1",words:"227"}),_,u,m,b,v,s("div",g,[B,s("div",k,[s("div",w,[f,A,s("pre",D,[E,s("div",T,[s("code",null,[C,s("div",x,[s("span",S,[a(e,null,{default:l(()=>[P]),_:1})]),z,V,I,N]),q,F])])]),s("pre",O,[$,s("div",R,[s("code",null,[Y,s("div",j,[s("span",J,[a(e,null,{default:l(()=>[G]),_:1})]),K,L,W,Z]),H,M])])]),Q]),U])]),X,ss,os])}const hs=c(y,[["render",as]]);export{ys as __pageData,hs as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.8032d46f.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.8032d46f.lean.js deleted file mode 100644 index 556034d7..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_errors.md.8032d46f.lean.js +++ /dev/null @@ -1,9 +0,0 @@ -import{_ as r}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as c,C as p,o as i,c as d,H as a,k as s,w as l,a as o,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const ys=JSON.parse('{"title":"Errors","description":"Raise compiler errors in your code examples to show incorrect states.","frontmatter":{"description":"Raise compiler errors in your code examples to show incorrect states.","title":"Errors"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/errors.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/errors.md","lastUpdated":1695377563000}'),y={name:"application/vitepress-plugin-shiki-twoslash/api/errors.md"},h=s("h1",{id:"errors",tabindex:"-1"},[o("Errors "),s("a",{class:"header-anchor",href:"#errors","aria-label":'Permalink to "Errors"'},"​")],-1),_=s("p",null,"Most of the time, you want to avoid errors in your code examples. Strictly speaking, this usually means setting the right compiler flags and environment in each code example.",-1),u=s("p",null,"Sometimes however, you do want to raise a compiler error — to show incorrect states. In those cases, twoslash has a way to mark the compiler errors you expect.",-1),m=s("h2",{id:"errors-num",tabindex:"-1"},[s("code",null,"@errors: [num]"),o(),s("a",{class:"header-anchor",href:"#errors-num","aria-label":'Permalink to "`@errors: [num]`"'},"​")],-1),b=s("p",null,"All TypeScript compiler errors have a number, this number is relatively arbitrary and can change between TypeScript versions. For our case these numbers are useul in declaring what we expect to see.",-1),v=s("p",null,[o("You can use "),s("code",null,"// @errors: [num]"),o(" to tell Twoslash that you expect this error to occur. This moves the compiler error message into the code example.")],-1),g={class:"vp-code-group vp-adaptive-theme"},B=n("",1),k={class:"blocks"},w={class:"language-ts vp-adaptive-theme active line-numbers-mode"},f=s("button",{title:"Copy Code",class:"copy"},null,-1),A=s("span",{class:"lang"},"ts",-1),D={class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},E=s("div",{class:"language-id"},"ts",-1),T={class:"code-container"},C=s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")],-1),x={class:"line"},S={style:{color:"#268BD2"}},P=s("data-lsp",{lsp:"const a: any"},"a",-1),z=s("span",{style:{color:"#839496"}}," ",-1),V=s("span",{style:{color:"#859900"}},"=",-1),I=s("span",{style:{color:"#839496"}}," ",-1),N=s("span",{style:{color:"#D33682"}},"132",-1),q=s("span",{class:"error"},[s("span",null,"Cannot assign to 'a' because it is a constant."),s("span",{class:"code"},"2588")],-1),F=s("span",{class:"error-behind"},"Cannot assign to 'a' because it is a constant.",-1),O={class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},$=s("div",{class:"language-id"},"ts",-1),R={class:"code-container"},Y=s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")],-1),j={class:"line"},J={style:{color:"#268BD2"}},G=s("data-lsp",{lsp:"const a: any"},"a",-1),K=s("span",{style:{color:"#657B83"}}," ",-1),L=s("span",{style:{color:"#859900"}},"=",-1),W=s("span",{style:{color:"#657B83"}}," ",-1),Z=s("span",{style:{color:"#D33682"}},"132",-1),H=s("span",{class:"error"},[s("span",null,"Cannot assign to 'a' because it is a constant."),s("span",{class:"code"},"2588")],-1),M=s("span",{class:"error-behind"},"Cannot assign to 'a' because it is a constant.",-1),Q=s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")],-1),U=n("",1),X=s("h2",{id:"noerrors",tabindex:"-1"},[s("code",null,"@noErrors"),o(),s("a",{class:"header-anchor",href:"#noerrors","aria-label":'Permalink to "`@noErrors`"'},"​")],-1),ss=s("p",null,[o("Sometimes you have needs in which a broken TypeScript build is okay. A good example of this is using a "),s("a",{href:"./queries#completions"},"completion query"),o(", which requires a broken TypeScript project to work. You can use "),s("code",null,"// @noErrors"),o(" to supress all errors in a code sample, and not have them show inline.")],-1),os=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-1ZJGh",id:"tab-POfuhrh",checked:"checked"}),s("label",{for:"tab-POfuhrh"},"output"),s("input",{type:"radio",name:"group-1ZJGh",id:"tab-_OVEf2b"}),s("label",{for:"tab-_OVEf2b"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const a: any"},"a")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#D33682"}},"132")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const a: "123"'},"a")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const a: any"},"a")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#D33682"}},"132")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @noErrors")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#D33682"}},"132")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @noErrors")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'123'")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#D33682"}},"132")]),o(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1);function as(es,ls,ns,ts,rs,cs){const t=r,e=p("data-err");return i(),d("div",null,[h,a(t,{readTime:"1",words:"227"}),_,u,m,b,v,s("div",g,[B,s("div",k,[s("div",w,[f,A,s("pre",D,[E,s("div",T,[s("code",null,[C,s("div",x,[s("span",S,[a(e,null,{default:l(()=>[P]),_:1})]),z,V,I,N]),q,F])])]),s("pre",O,[$,s("div",R,[s("code",null,[Y,s("div",j,[s("span",J,[a(e,null,{default:l(()=>[G]),_:1})]),K,L,W,Z]),H,M])])]),Q]),U])]),X,ss,os])}const hs=c(y,[["render",as]]);export{ys as __pageData,hs as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.b534e723.js b/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.b534e723.js new file mode 100644 index 00000000..ea26e221 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.b534e723.js @@ -0,0 +1,99 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as t,c as r,H as p,k as s,a as e,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const U=JSON.parse('{"title":"Includes","description":"Include re-usable TypeScript blocks in your code examples.","frontmatter":{"description":"Include re-usable TypeScript blocks in your code examples.","title":"Includes"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/includes.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/includes.md","lastUpdated":1699051935000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/includes.md"},i=s("h1",{id:"includes",tabindex:"-1"},[e("Includes "),s("a",{class:"header-anchor",href:"#includes","aria-label":'Permalink to "Includes"'},"​")],-1),y=l('

    As your documentation grows, you may need a way of re-using code blocks to prevent code duplication. Shiki Twoslash provides a simple includes system.

    Defining a re-usable block

    Re-usable code blocks are defined by the twoslash language, followed by the include keyword and the reference name of your choice.

    md
    ```twoslash include myBlock\ntype SomeString = string\n```
    ```twoslash include myBlock\ntype SomeString = string\n```

    Incremental steps

    Shiki Twoslash also provide the ability to define incremental steps through the definition of re-usable blocks. This means whenever a new step is delimited down the code, it will also include previous steps. These are not groups.

    • Incremental steps are delimited by // - [name of the step]
    • They are named at the end of the actual code
    md
    ```twoslash include myBlockWithSteps\ntype SomeString = string\n// - base\ntype SomeUser = { name: string; mail?: SomeUserMail }\ntype SomeUserMail = { content: string; verified: boolean }\n// - afterUserDefinitions\ntype SomeGroup = { name: string; members: SomeUser[] }\n// - afterGroupDefinitions\n```
    ```twoslash include myBlockWithSteps\ntype SomeString = string\n// - base\ntype SomeUser = { name: string; mail?: SomeUserMail }\ntype SomeUserMail = { content: string; verified: boolean }\n// - afterUserDefinitions\ntype SomeGroup = { name: string; members: SomeUser[] }\n// - afterGroupDefinitions\n```

    Including a whole block

    To include a re-usable block, add // @include: [block name] in your code block.

    twoslash
    ',11),d=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-zv9DY",id:"tab-F4zlFCM",checked:"checked"}),s("label",{for:"tab-F4zlFCM"},"output"),s("input",{type:"radio",name:"group-zv9DY",id:"tab-pTFY48K"}),s("label",{for:"tab-pTFY48K"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const a: string"},"a")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'string'")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const a: string"},"a")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'string'")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```twoslash include myBlock")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @include: myBlock")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"a"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"SomeString"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'string'")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```twoslash include myBlock")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @include: myBlock")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"a"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"SomeString"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'string'")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br")])])])],-1),m=l('

    Including a block step

    To include a re-usable block at a specific step, add // @include: [block name]-[step name] in your code block.

    twoslash
    ',3),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-bUutw",id:"tab-tASupf3",checked:"checked"}),s("label",{for:"tab-tASupf3"},"output"),s("input",{type:"radio",name:"group-bUutw",id:"tab-vti8P6X"}),s("label",{for:"tab-vti8P6X"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUser = { + name: string; + mail?: SomeUserMail | undefined; +}`},"SomeUser")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," { "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}},"; "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) mail?: SomeUserMail | undefined"},"mail")]),s("span",{style:{color:"#F47067"}},"?:"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#ADBAC7"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," { "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) content: string"},"content")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}},"; "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) verified: boolean"},"verified")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"boolean"),s("span",{style:{color:"#ADBAC7"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}},[e(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),e(": ")]),s("span",{style:{color:"#96D0FF"}},"'some-email'"),s("span",{style:{color:"#ADBAC7"}},[e(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),e(": ")]),s("span",{style:{color:"#6CB6FF"}},"true"),s("span",{style:{color:"#ADBAC7"}}," }")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUser = { + name: string; + mail?: SomeUserMail | undefined; +}`},"SomeUser")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," { "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}},"; "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) mail?: SomeUserMail | undefined"},"mail")]),s("span",{style:{color:"#D73A49"}},"?:"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#24292E"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," { "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) content: string"},"content")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}},"; "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) verified: boolean"},"verified")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"boolean"),s("span",{style:{color:"#24292E"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}},[e(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),e(": ")]),s("span",{style:{color:"#032F62"}},"'some-email'"),s("span",{style:{color:"#24292E"}},[e(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),e(": ")]),s("span",{style:{color:"#005CC5"}},"true"),s("span",{style:{color:"#24292E"}}," }")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```twoslash include myBlockWithSteps")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - base")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeUserMail = { content: string; verified: boolean }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - afterGroupDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"mail"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"SomeUserMail"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," { content: "),s("span",{style:{color:"#96D0FF"}},"'some-email'"),s("span",{style:{color:"#ADBAC7"}},", verified: "),s("span",{style:{color:"#6CB6FF"}},"true"),s("span",{style:{color:"#ADBAC7"}}," }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```twoslash include myBlockWithSteps")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - base")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeUserMail = { content: string; verified: boolean }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - afterGroupDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"mail"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"SomeUserMail"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," { content: "),s("span",{style:{color:"#032F62"}},"'some-email'"),s("span",{style:{color:"#24292E"}},", verified: "),s("span",{style:{color:"#005CC5"}},"true"),s("span",{style:{color:"#24292E"}}," }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br")])])])],-1),b=s("h2",{id:"hiding-re-used-code",tabindex:"-1"},[e("Hiding re-used code "),s("a",{class:"header-anchor",href:"#hiding-re-used-code","aria-label":'Permalink to "Hiding re-used code"'},"​")],-1),A=s("p",null,[e("Re-using a lot of TypeScript code can easily bloat your documentation and obstruct the main point of your code block. You can hide re-used code to keep your code blocks clean and concise by "),s("a",{href:"./cutting"},"cutting"),e(" right after the "),s("code",null,"@include"),e(" statement.")],-1),g=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-5p6kj",id:"tab-W6TJfjn",checked:"checked"}),s("label",{for:"tab-W6TJfjn"},"output"),s("input",{type:"radio",name:"group-5p6kj",id:"tab-c_4GIzU"}),s("label",{for:"tab-c_4GIzU"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}},[e(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),e(": ")]),s("span",{style:{color:"#96D0FF"}},"'some-email'"),s("span",{style:{color:"#ADBAC7"}},[e(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),e(": ")]),s("span",{style:{color:"#6CB6FF"}},"true"),s("span",{style:{color:"#ADBAC7"}}," }")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}},[e(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),e(": ")]),s("span",{style:{color:"#032F62"}},"'some-email'"),s("span",{style:{color:"#24292E"}},[e(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),e(": ")]),s("span",{style:{color:"#005CC5"}},"true"),s("span",{style:{color:"#24292E"}}," }")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```twoslash include myBlockWithSteps")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - base")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeUserMail = { content: string; verified: boolean }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - afterGroupDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"mail"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"SomeUserMail"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," { content: "),s("span",{style:{color:"#96D0FF"}},"'some-email'"),s("span",{style:{color:"#ADBAC7"}},", verified: "),s("span",{style:{color:"#6CB6FF"}},"true"),s("span",{style:{color:"#ADBAC7"}}," }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```twoslash include myBlockWithSteps")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - base")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeUserMail = { content: string; verified: boolean }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - afterGroupDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"mail"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"SomeUserMail"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," { content: "),s("span",{style:{color:"#032F62"}},"'some-email'"),s("span",{style:{color:"#24292E"}},", verified: "),s("span",{style:{color:"#005CC5"}},"true"),s("span",{style:{color:"#24292E"}}," }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br"),s("span",{class:"line-number"},"15"),s("br")])])])],-1);function h(C,D,v,S,B,f){const n=a;return t(),r("div",null,[i,p(n,{readTime:"2",words:"431"}),y,d,m,u,b,A,g])}const w=o(c,[["render",h]]);export{U as __pageData,w as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.b534e723.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.b534e723.lean.js new file mode 100644 index 00000000..9f386192 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.b534e723.lean.js @@ -0,0 +1,99 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as t,c as r,H as p,k as s,a as e,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const U=JSON.parse('{"title":"Includes","description":"Include re-usable TypeScript blocks in your code examples.","frontmatter":{"description":"Include re-usable TypeScript blocks in your code examples.","title":"Includes"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/includes.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/includes.md","lastUpdated":1699051935000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/includes.md"},i=s("h1",{id:"includes",tabindex:"-1"},[e("Includes "),s("a",{class:"header-anchor",href:"#includes","aria-label":'Permalink to "Includes"'},"​")],-1),y=l("",11),d=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-zv9DY",id:"tab-F4zlFCM",checked:"checked"}),s("label",{for:"tab-F4zlFCM"},"output"),s("input",{type:"radio",name:"group-zv9DY",id:"tab-pTFY48K"}),s("label",{for:"tab-pTFY48K"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const a: string"},"a")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'string'")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const a: string"},"a")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'string'")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```twoslash include myBlock")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @include: myBlock")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"a"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"SomeString"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'string'")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```twoslash include myBlock")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @include: myBlock")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"a"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"SomeString"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'string'")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br")])])])],-1),m=l("",3),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-bUutw",id:"tab-tASupf3",checked:"checked"}),s("label",{for:"tab-tASupf3"},"output"),s("input",{type:"radio",name:"group-bUutw",id:"tab-vti8P6X"}),s("label",{for:"tab-vti8P6X"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUser = { + name: string; + mail?: SomeUserMail | undefined; +}`},"SomeUser")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," { "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}},"; "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) mail?: SomeUserMail | undefined"},"mail")]),s("span",{style:{color:"#F47067"}},"?:"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#ADBAC7"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," { "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) content: string"},"content")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}},"; "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) verified: boolean"},"verified")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"boolean"),s("span",{style:{color:"#ADBAC7"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}},[e(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),e(": ")]),s("span",{style:{color:"#96D0FF"}},"'some-email'"),s("span",{style:{color:"#ADBAC7"}},[e(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),e(": ")]),s("span",{style:{color:"#6CB6FF"}},"true"),s("span",{style:{color:"#ADBAC7"}}," }")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUser = { + name: string; + mail?: SomeUserMail | undefined; +}`},"SomeUser")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," { "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}},"; "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) mail?: SomeUserMail | undefined"},"mail")]),s("span",{style:{color:"#D73A49"}},"?:"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#24292E"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," { "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) content: string"},"content")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}},"; "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) verified: boolean"},"verified")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"boolean"),s("span",{style:{color:"#24292E"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}},[e(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),e(": ")]),s("span",{style:{color:"#032F62"}},"'some-email'"),s("span",{style:{color:"#24292E"}},[e(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),e(": ")]),s("span",{style:{color:"#005CC5"}},"true"),s("span",{style:{color:"#24292E"}}," }")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```twoslash include myBlockWithSteps")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - base")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeUserMail = { content: string; verified: boolean }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - afterGroupDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"mail"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"SomeUserMail"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," { content: "),s("span",{style:{color:"#96D0FF"}},"'some-email'"),s("span",{style:{color:"#ADBAC7"}},", verified: "),s("span",{style:{color:"#6CB6FF"}},"true"),s("span",{style:{color:"#ADBAC7"}}," }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```twoslash include myBlockWithSteps")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - base")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeUserMail = { content: string; verified: boolean }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - afterGroupDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"mail"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"SomeUserMail"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," { content: "),s("span",{style:{color:"#032F62"}},"'some-email'"),s("span",{style:{color:"#24292E"}},", verified: "),s("span",{style:{color:"#005CC5"}},"true"),s("span",{style:{color:"#24292E"}}," }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br")])])])],-1),b=s("h2",{id:"hiding-re-used-code",tabindex:"-1"},[e("Hiding re-used code "),s("a",{class:"header-anchor",href:"#hiding-re-used-code","aria-label":'Permalink to "Hiding re-used code"'},"​")],-1),A=s("p",null,[e("Re-using a lot of TypeScript code can easily bloat your documentation and obstruct the main point of your code block. You can hide re-used code to keep your code blocks clean and concise by "),s("a",{href:"./cutting"},"cutting"),e(" right after the "),s("code",null,"@include"),e(" statement.")],-1),g=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-5p6kj",id:"tab-W6TJfjn",checked:"checked"}),s("label",{for:"tab-W6TJfjn"},"output"),s("input",{type:"radio",name:"group-5p6kj",id:"tab-c_4GIzU"}),s("label",{for:"tab-c_4GIzU"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}},[e(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),e(": ")]),s("span",{style:{color:"#96D0FF"}},"'some-email'"),s("span",{style:{color:"#ADBAC7"}},[e(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),e(": ")]),s("span",{style:{color:"#6CB6FF"}},"true"),s("span",{style:{color:"#ADBAC7"}}," }")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type SomeUserMail = { + content: string; + verified: boolean; +}`},"SomeUserMail")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}},[e(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),e(": ")]),s("span",{style:{color:"#032F62"}},"'some-email'"),s("span",{style:{color:"#24292E"}},[e(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),e(": ")]),s("span",{style:{color:"#005CC5"}},"true"),s("span",{style:{color:"#24292E"}}," }")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```twoslash include myBlockWithSteps")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - base")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeUserMail = { content: string; verified: boolean }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"// - afterGroupDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"mail"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"SomeUserMail"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," { content: "),s("span",{style:{color:"#96D0FF"}},"'some-email'"),s("span",{style:{color:"#ADBAC7"}},", verified: "),s("span",{style:{color:"#6CB6FF"}},"true"),s("span",{style:{color:"#ADBAC7"}}," }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```twoslash include myBlockWithSteps")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeString = string")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - base")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeUserMail = { content: string; verified: boolean }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"// - afterGroupDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")]),e(` +`),s("span",{class:"line"}),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"mail"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"SomeUserMail"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," { content: "),s("span",{style:{color:"#032F62"}},"'some-email'"),s("span",{style:{color:"#24292E"}},", verified: "),s("span",{style:{color:"#005CC5"}},"true"),s("span",{style:{color:"#24292E"}}," }")]),e(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br"),s("span",{class:"line-number"},"15"),s("br")])])])],-1);function h(C,D,v,S,B,f){const n=a;return t(),r("div",null,[i,p(n,{readTime:"2",words:"431"}),y,d,m,u,b,A,g])}const w=o(c,[["render",h]]);export{U as __pageData,w as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.d69b2a67.js b/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.d69b2a67.js deleted file mode 100644 index 7782d5a3..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.d69b2a67.js +++ /dev/null @@ -1,99 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as t,c as r,H as p,k as s,a as l,Q as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const M=JSON.parse('{"title":"Includes","description":"Include re-usable TypeScript blocks in your code examples.","frontmatter":{"description":"Include re-usable TypeScript blocks in your code examples.","title":"Includes"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/includes.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/includes.md","lastUpdated":1695377563000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/includes.md"},i=s("h1",{id:"includes",tabindex:"-1"},[l("Includes "),s("a",{class:"header-anchor",href:"#includes","aria-label":'Permalink to "Includes"'},"​")],-1),d=e('

    As your documentation grows, you may need a way of re-using code blocks to prevent code duplication. Shiki Twoslash provides a simple includes system.

    Defining a re-usable block

    Re-usable code blocks are defined by the twoslash language, followed by the include keyword and the reference name of your choice.

    md
    ```twoslash include myBlock\ntype SomeString = string\n```
    ```twoslash include myBlock\ntype SomeString = string\n```

    Incremental steps

    Shiki Twoslash also provide the ability to define incremental steps through the definition of re-usable blocks. This means whenever a new step is delimited down the code, it will also include previous steps. These are not groups.

    • Incremental steps are delimited by // - [name of the step]
    • They are named at the end of the actual code
    md
    ```twoslash include myBlockWithSteps\ntype SomeString = string\n// - base\ntype SomeUser = { name: string; mail?: SomeUserMail }\ntype SomeUserMail = { content: string; verified: boolean }\n// - afterUserDefinitions\ntype SomeGroup = { name: string; members: SomeUser[] }\n// - afterGroupDefinitions\n```
    ```twoslash include myBlockWithSteps\ntype SomeString = string\n// - base\ntype SomeUser = { name: string; mail?: SomeUserMail }\ntype SomeUserMail = { content: string; verified: boolean }\n// - afterUserDefinitions\ntype SomeGroup = { name: string; members: SomeUser[] }\n// - afterGroupDefinitions\n```

    Including a whole block

    To include a re-usable block, add // @include: [block name] in your code block.

    twoslash
    ',11),y=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-rexp6",id:"tab-eibzeKv",checked:"checked"}),s("label",{for:"tab-eibzeKv"},"output"),s("input",{type:"radio",name:"group-rexp6",id:"tab-GO6ltP4"}),s("label",{for:"tab-GO6ltP4"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const a: string"},"a")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'string'")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const a: string"},"a")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'string'")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```twoslash include myBlock")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @include: myBlock")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeString"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'string'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```twoslash include myBlock")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @include: myBlock")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeString"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'string'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br")])])])],-1),m=e('

    Including a block step

    To include a re-usable block at a specific step, add // @include: [block name]-[step name] in your code block.

    twoslash
    ',3),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-T_X39",id:"tab-iH-2cep",checked:"checked"}),s("label",{for:"tab-iH-2cep"},"output"),s("input",{type:"radio",name:"group-T_X39",id:"tab-q89R72p"}),s("label",{for:"tab-q89R72p"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUser = { - name: string; - mail?: SomeUserMail | undefined; -}`},"SomeUser")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}},[l(" { "),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}},[l("; "),s("data-lsp",{lsp:"(property) mail?: SomeUserMail | undefined"},"mail")]),s("span",{style:{color:"#859900"}},"?:"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#839496"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}},[l("; "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"boolean"),s("span",{style:{color:"#839496"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),l(": ")]),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#839496"}},[l(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),l(": ")]),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#839496"}}," }")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUser = { - name: string; - mail?: SomeUserMail | undefined; -}`},"SomeUser")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}},[l(" { "),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}},[l("; "),s("data-lsp",{lsp:"(property) mail?: SomeUserMail | undefined"},"mail")]),s("span",{style:{color:"#859900"}},"?:"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#657B83"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}},[l("; "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"boolean"),s("span",{style:{color:"#657B83"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),l(": ")]),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#657B83"}},[l(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),l(": ")]),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#657B83"}}," }")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```twoslash include myBlockWithSteps")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - base")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeUserMail = { content: string; verified: boolean }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - afterGroupDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"mail"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeUserMail"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," { content: "),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#839496"}},", verified: "),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#839496"}}," }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```twoslash include myBlockWithSteps")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - base")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeUserMail = { content: string; verified: boolean }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - afterGroupDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"mail"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeUserMail"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," { content: "),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#657B83"}},", verified: "),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#657B83"}}," }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br")])])])],-1),b=s("h2",{id:"hiding-re-used-code",tabindex:"-1"},[l("Hiding re-used code "),s("a",{class:"header-anchor",href:"#hiding-re-used-code","aria-label":'Permalink to "Hiding re-used code"'},"​")],-1),g=s("p",null,[l("Re-using a lot of TypeScript code can easily bloat your documentation and obstruct the main point of your code block. You can hide re-used code to keep your code blocks clean and concise by "),s("a",{href:"./cutting"},"cutting"),l(" right after the "),s("code",null,"@include"),l(" statement.")],-1),B=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-MqRuy",id:"tab-MXNBgnY",checked:"checked"}),s("label",{for:"tab-MXNBgnY"},"output"),s("input",{type:"radio",name:"group-MqRuy",id:"tab-RlExHh_"}),s("label",{for:"tab-RlExHh_"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),l(": ")]),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#839496"}},[l(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),l(": ")]),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#839496"}}," }")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),l(": ")]),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#657B83"}},[l(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),l(": ")]),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#657B83"}}," }")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```twoslash include myBlockWithSteps")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - base")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeUserMail = { content: string; verified: boolean }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - afterGroupDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"mail"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeUserMail"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," { content: "),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#839496"}},", verified: "),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#839496"}}," }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```twoslash include myBlockWithSteps")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - base")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeUserMail = { content: string; verified: boolean }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - afterGroupDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"mail"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeUserMail"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," { content: "),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#657B83"}},", verified: "),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#657B83"}}," }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br"),s("span",{class:"line-number"},"15"),s("br")])])])],-1);function h(v,S,f,k,U,w){const n=a;return t(),r("div",null,[i,p(n,{readTime:"2",words:"431"}),d,y,m,u,b,g,B])}const D=o(c,[["render",h]]);export{M as __pageData,D as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.d69b2a67.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.d69b2a67.lean.js deleted file mode 100644 index 94ecb939..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_includes.md.d69b2a67.lean.js +++ /dev/null @@ -1,99 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as t,c as r,H as p,k as s,a as l,Q as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const M=JSON.parse('{"title":"Includes","description":"Include re-usable TypeScript blocks in your code examples.","frontmatter":{"description":"Include re-usable TypeScript blocks in your code examples.","title":"Includes"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/includes.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/includes.md","lastUpdated":1695377563000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/includes.md"},i=s("h1",{id:"includes",tabindex:"-1"},[l("Includes "),s("a",{class:"header-anchor",href:"#includes","aria-label":'Permalink to "Includes"'},"​")],-1),d=e("",11),y=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-rexp6",id:"tab-eibzeKv",checked:"checked"}),s("label",{for:"tab-eibzeKv"},"output"),s("input",{type:"radio",name:"group-rexp6",id:"tab-GO6ltP4"}),s("label",{for:"tab-GO6ltP4"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const a: string"},"a")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'string'")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const a: string"},"a")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'string'")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```twoslash include myBlock")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @include: myBlock")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeString"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'string'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```twoslash include myBlock")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @include: myBlock")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"a"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeString"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'string'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br")])])])],-1),m=e("",3),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-T_X39",id:"tab-iH-2cep",checked:"checked"}),s("label",{for:"tab-iH-2cep"},"output"),s("input",{type:"radio",name:"group-T_X39",id:"tab-q89R72p"}),s("label",{for:"tab-q89R72p"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUser = { - name: string; - mail?: SomeUserMail | undefined; -}`},"SomeUser")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}},[l(" { "),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}},[l("; "),s("data-lsp",{lsp:"(property) mail?: SomeUserMail | undefined"},"mail")]),s("span",{style:{color:"#859900"}},"?:"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#839496"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}},[l("; "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"boolean"),s("span",{style:{color:"#839496"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),l(": ")]),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#839496"}},[l(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),l(": ")]),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#839496"}}," }")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type SomeString = string"},"SomeString")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUser = { - name: string; - mail?: SomeUserMail | undefined; -}`},"SomeUser")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}},[l(" { "),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}},[l("; "),s("data-lsp",{lsp:"(property) mail?: SomeUserMail | undefined"},"mail")]),s("span",{style:{color:"#859900"}},"?:"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#657B83"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}},[l("; "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"boolean"),s("span",{style:{color:"#657B83"}}," }")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),l(": ")]),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#657B83"}},[l(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),l(": ")]),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#657B83"}}," }")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```twoslash include myBlockWithSteps")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - base")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeUserMail = { content: string; verified: boolean }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - afterGroupDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"mail"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeUserMail"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," { content: "),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#839496"}},", verified: "),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#839496"}}," }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```twoslash include myBlockWithSteps")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - base")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeUserMail = { content: string; verified: boolean }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - afterGroupDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"mail"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeUserMail"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," { content: "),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#657B83"}},", verified: "),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#657B83"}}," }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br")])])])],-1),b=s("h2",{id:"hiding-re-used-code",tabindex:"-1"},[l("Hiding re-used code "),s("a",{class:"header-anchor",href:"#hiding-re-used-code","aria-label":'Permalink to "Hiding re-used code"'},"​")],-1),g=s("p",null,[l("Re-using a lot of TypeScript code can easily bloat your documentation and obstruct the main point of your code block. You can hide re-used code to keep your code blocks clean and concise by "),s("a",{href:"./cutting"},"cutting"),l(" right after the "),s("code",null,"@include"),l(" statement.")],-1),B=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-MqRuy",id:"tab-MXNBgnY",checked:"checked"}),s("label",{for:"tab-MXNBgnY"},"output"),s("input",{type:"radio",name:"group-MqRuy",id:"tab-RlExHh_"}),s("label",{for:"tab-RlExHh_"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),l(": ")]),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#839496"}},[l(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),l(": ")]),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#839496"}}," }")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const mail: SomeUserMail"},"mail")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type SomeUserMail = { - content: string; - verified: boolean; -}`},"SomeUserMail")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}},[l(" { "),s("data-lsp",{lsp:"(property) content: string"},"content"),l(": ")]),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#657B83"}},[l(", "),s("data-lsp",{lsp:"(property) verified: boolean"},"verified"),l(": ")]),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#657B83"}}," }")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```twoslash include myBlockWithSteps")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - base")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeUserMail = { content: string; verified: boolean }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"// - afterGroupDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"mail"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeUserMail"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," { content: "),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#839496"}},", verified: "),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#839496"}}," }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```twoslash include myBlockWithSteps")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeString = string")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - base")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeUser = { name: string; mail?: SomeUserMail }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeUserMail = { content: string; verified: boolean }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"type SomeGroup = { name: string; members: SomeUser[] }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"// - afterGroupDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @include: myBlockWithSteps-afterUserDefinitions")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"mail"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},"SomeUserMail"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," { content: "),s("span",{style:{color:"#2AA198"}},"'some-email'"),s("span",{style:{color:"#657B83"}},", verified: "),s("span",{style:{color:"#B58900"}},"true"),s("span",{style:{color:"#657B83"}}," }")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br"),s("span",{class:"line-number"},"15"),s("br")])])])],-1);function h(v,S,f,k,U,w){const n=a;return t(),r("div",null,[i,p(n,{readTime:"2",words:"431"}),d,y,m,u,b,g,B])}const D=o(c,[["render",h]]);export{M as __pageData,D as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.8b741477.js b/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.8b741477.js new file mode 100644 index 00000000..bd489d73 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.8b741477.js @@ -0,0 +1,20 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as r,k as l,a as s,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const f=JSON.parse('{"title":"Logging","description":"Display formatted output for code examples.","frontmatter":{"description":"Display formatted output for code examples.","title":"Logging","keywords":["console","javascript","typescript","showcase","snippets"]},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/logging.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/logging.md","lastUpdated":1699051935000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/logging.md"},p=l("h1",{id:"logging",tabindex:"-1"},[s("Logging "),l("a",{class:"header-anchor",href:"#logging","aria-label":'Permalink to "Logging"'},"​")],-1),d=i('

    When you first see a Twoslash code example with an inline compiler error, you instinctively trust that the compiler error is correct because the design shows that it is not a part of the code sample. The logging tools lets you do that, but abuses the systemic trust because your code is not being evaluated to generate the logs.

    This feature is effectively a facade, people will trust your output and it will look better.

    @log:, @warn:, @error:

    The names are based on the functions on the console object:

    ',4),g=l("div",{class:"vp-code-group vp-adaptive-theme"},[l("div",{class:"tabs"},[l("input",{type:"radio",name:"group-5qzOF",id:"tab-X_BVc45",checked:"checked"}),l("label",{for:"tab-X_BVc45"},"output"),l("input",{type:"radio",name:"group-5qzOF",id:"tab-57Euuoa"}),l("label",{for:"tab-57Euuoa"},"markdown")]),l("div",{class:"blocks"},[l("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[l("button",{title:"Copy Code",class:"copy"}),l("span",{class:"lang"},"ts"),l("pre",null,[l("code",{class:"language-ts"},[l("div",{class:"tag-container"},[l("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[l("div",{class:"language-id"},"ts"),l("div",{class:"code-container"},[l("code",null,[l("div",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#DCBDFB"}},[l("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello log'"),l("span",{style:{color:"#ADBAC7"}},")")]),l("div",{class:"meta-line logger log-log"},[l("svg",{width:"12",height:"15",viewBox:"0 0 12 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M5.76822 0.359816C5.41466 -0.0644613 4.78409 -0.121785 4.35982 0.231779C3.93554 0.585343 3.87821 1.21591 4.23178 1.64018L5.76822 0.359816ZM10 7L10.7926 7.60971L11.2809 6.97499L10.7682 6.35982L10 7ZM4.20738 12.8903C3.87064 13.328 3.95254 13.9559 4.39029 14.2926C4.82804 14.6294 5.45589 14.5475 5.79262 14.1097L4.20738 12.8903ZM4.23178 1.64018L9.23178 7.64018L10.7682 6.35982L5.76822 0.359816L4.23178 1.64018ZM9.20738 6.39029L4.20738 12.8903L5.79262 14.1097L10.7926 7.60971L9.20738 6.39029Z",fill:"#BDBDBD"}),l("line",{y1:"3.5",x2:"4",y2:"3.5",stroke:"#BDBDBD"}),l("path",{d:"M0 7H4",stroke:"#BDBDBD"}),l("line",{y1:"10.5",x2:"4",y2:"10.5",stroke:"#BDBDBD"})]),l("span",{class:"message"},"Hello log")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#DCBDFB"}},[l("data-lsp",{lsp:"(method) Console.warn(...data: any[]): void"},"warn")]),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello warn'"),l("span",{style:{color:"#ADBAC7"}},")")]),l("div",{class:"meta-line logger warn-log"},[l("svg",{width:"21",height:"18",viewBox:"0 0 21 18",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M9.63401 0.5C10.0189 -0.166667 10.9812 -0.166667 11.3661 0.5L20.4593 16.25C20.8442 16.9167 20.3631 17.75 19.5933 17.75H1.40676C0.636965 17.75 0.15584 16.9167 0.54074 16.25L9.63401 0.5Z",fill:"#E5A604"}),l("rect",{x:"9",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"9",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello warn")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#DCBDFB"}},[l("data-lsp",{lsp:"(method) Console.error(...data: any[]): void"},"error")]),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello error'"),l("span",{style:{color:"#ADBAC7"}},")")]),l("div",{class:"meta-line logger error-log"},[l("svg",{width:"19",height:"19",viewBox:"0 0 19 19",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M4.63018 1.29289L1.29289 4.63018C1.10536 4.81772 1 5.07207 1 5.33729V13.6627C1 13.9279 1.10536 14.1823 1.29289 14.3698L4.63018 17.7071C4.81772 17.8946 5.07207 18 5.33729 18H13.6627C13.9279 18 14.1823 17.8946 14.3698 17.7071L17.7071 14.3698C17.8946 14.1823 18 13.9279 18 13.6627V5.33729C18 5.07207 17.8946 4.81772 17.7071 4.63018L14.3698 1.29289C14.1823 1.10536 13.9279 1 13.6627 1H5.33729C5.07207 1 4.81772 1.10536 4.63018 1.29289Z",fill:"#E72622",stroke:"#E72622"}),l("rect",{x:"8",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"8",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello error")])])])])]),s(` +`),l("div",{class:"tag-container"},[l("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[l("div",{class:"language-id"},"ts"),l("div",{class:"code-container"},[l("code",null,[l("div",{class:"line"},[l("span",{style:{color:"#24292E"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#6F42C1"}},[l("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello log'"),l("span",{style:{color:"#24292E"}},")")]),l("div",{class:"meta-line logger log-log"},[l("svg",{width:"12",height:"15",viewBox:"0 0 12 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M5.76822 0.359816C5.41466 -0.0644613 4.78409 -0.121785 4.35982 0.231779C3.93554 0.585343 3.87821 1.21591 4.23178 1.64018L5.76822 0.359816ZM10 7L10.7926 7.60971L11.2809 6.97499L10.7682 6.35982L10 7ZM4.20738 12.8903C3.87064 13.328 3.95254 13.9559 4.39029 14.2926C4.82804 14.6294 5.45589 14.5475 5.79262 14.1097L4.20738 12.8903ZM4.23178 1.64018L9.23178 7.64018L10.7682 6.35982L5.76822 0.359816L4.23178 1.64018ZM9.20738 6.39029L4.20738 12.8903L5.79262 14.1097L10.7926 7.60971L9.20738 6.39029Z",fill:"#BDBDBD"}),l("line",{y1:"3.5",x2:"4",y2:"3.5",stroke:"#BDBDBD"}),l("path",{d:"M0 7H4",stroke:"#BDBDBD"}),l("line",{y1:"10.5",x2:"4",y2:"10.5",stroke:"#BDBDBD"})]),l("span",{class:"message"},"Hello log")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#24292E"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#6F42C1"}},[l("data-lsp",{lsp:"(method) Console.warn(...data: any[]): void"},"warn")]),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello warn'"),l("span",{style:{color:"#24292E"}},")")]),l("div",{class:"meta-line logger warn-log"},[l("svg",{width:"21",height:"18",viewBox:"0 0 21 18",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M9.63401 0.5C10.0189 -0.166667 10.9812 -0.166667 11.3661 0.5L20.4593 16.25C20.8442 16.9167 20.3631 17.75 19.5933 17.75H1.40676C0.636965 17.75 0.15584 16.9167 0.54074 16.25L9.63401 0.5Z",fill:"#E5A604"}),l("rect",{x:"9",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"9",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello warn")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#24292E"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#6F42C1"}},[l("data-lsp",{lsp:"(method) Console.error(...data: any[]): void"},"error")]),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello error'"),l("span",{style:{color:"#24292E"}},")")]),l("div",{class:"meta-line logger error-log"},[l("svg",{width:"19",height:"19",viewBox:"0 0 19 19",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M4.63018 1.29289L1.29289 4.63018C1.10536 4.81772 1 5.07207 1 5.33729V13.6627C1 13.9279 1.10536 14.1823 1.29289 14.3698L4.63018 17.7071C4.81772 17.8946 5.07207 18 5.33729 18H13.6627C13.9279 18 14.1823 17.8946 14.3698 17.7071L17.7071 14.3698C17.8946 14.1823 18 13.9279 18 13.6627V5.33729C18 5.07207 17.8946 4.81772 17.7071 4.63018L14.3698 1.29289C14.1823 1.10536 13.9279 1 13.6627 1H5.33729C5.07207 1 4.81772 1.10536 4.63018 1.29289Z",fill:"#E72622",stroke:"#E72622"}),l("rect",{x:"8",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"8",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello error")])])])])])])]),l("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[l("span",{class:"line-number"},"1"),l("br")])]),l("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[l("button",{title:"Copy Code",class:"copy"}),l("span",{class:"lang"},"md"),l("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[l("code",null,[l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"console."),l("span",{style:{color:"#DCBDFB"}},"log"),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello log'"),l("span",{style:{color:"#ADBAC7"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#768390"}},"// @log: Hello log")]),s(` +`),l("span",{class:"line"}),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"console."),l("span",{style:{color:"#DCBDFB"}},"warn"),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello warn'"),l("span",{style:{color:"#ADBAC7"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#768390"}},"// @warn: Hello warn")]),s(` +`),l("span",{class:"line"}),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"console."),l("span",{style:{color:"#DCBDFB"}},"error"),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello error'"),l("span",{style:{color:"#ADBAC7"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#768390"}},"// @error: Hello error")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"```")])])]),l("pre",{class:"shiki github-light vp-code-light"},[l("code",null,[l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"```ts twoslash")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"console."),l("span",{style:{color:"#6F42C1"}},"log"),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello log'"),l("span",{style:{color:"#24292E"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#6A737D"}},"// @log: Hello log")]),s(` +`),l("span",{class:"line"}),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"console."),l("span",{style:{color:"#6F42C1"}},"warn"),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello warn'"),l("span",{style:{color:"#24292E"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#6A737D"}},"// @warn: Hello warn")]),s(` +`),l("span",{class:"line"}),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"console."),l("span",{style:{color:"#6F42C1"}},"error"),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello error'"),l("span",{style:{color:"#24292E"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#6A737D"}},"// @error: Hello error")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"```")])])]),l("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[l("span",{class:"line-number"},"1"),l("br"),l("span",{class:"line-number"},"2"),l("br"),l("span",{class:"line-number"},"3"),l("br"),l("span",{class:"line-number"},"4"),l("br"),l("span",{class:"line-number"},"5"),l("br"),l("span",{class:"line-number"},"6"),l("br"),l("span",{class:"line-number"},"7"),l("br"),l("span",{class:"line-number"},"8"),l("br"),l("span",{class:"line-number"},"9"),l("br"),l("span",{class:"line-number"},"10"),l("br")])])])],-1);function h(y,w,m,C,v,u){const e=o;return n(),t("div",null,[p,r(e,{readTime:"1",words:"152"}),d,g])}const A=a(c,[["render",h]]);export{f as __pageData,A as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.8b741477.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.8b741477.lean.js new file mode 100644 index 00000000..2944f08c --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.8b741477.lean.js @@ -0,0 +1,20 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as r,k as l,a as s,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const f=JSON.parse('{"title":"Logging","description":"Display formatted output for code examples.","frontmatter":{"description":"Display formatted output for code examples.","title":"Logging","keywords":["console","javascript","typescript","showcase","snippets"]},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/logging.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/logging.md","lastUpdated":1699051935000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/logging.md"},p=l("h1",{id:"logging",tabindex:"-1"},[s("Logging "),l("a",{class:"header-anchor",href:"#logging","aria-label":'Permalink to "Logging"'},"​")],-1),d=i("",4),g=l("div",{class:"vp-code-group vp-adaptive-theme"},[l("div",{class:"tabs"},[l("input",{type:"radio",name:"group-5qzOF",id:"tab-X_BVc45",checked:"checked"}),l("label",{for:"tab-X_BVc45"},"output"),l("input",{type:"radio",name:"group-5qzOF",id:"tab-57Euuoa"}),l("label",{for:"tab-57Euuoa"},"markdown")]),l("div",{class:"blocks"},[l("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[l("button",{title:"Copy Code",class:"copy"}),l("span",{class:"lang"},"ts"),l("pre",null,[l("code",{class:"language-ts"},[l("div",{class:"tag-container"},[l("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[l("div",{class:"language-id"},"ts"),l("div",{class:"code-container"},[l("code",null,[l("div",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#DCBDFB"}},[l("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello log'"),l("span",{style:{color:"#ADBAC7"}},")")]),l("div",{class:"meta-line logger log-log"},[l("svg",{width:"12",height:"15",viewBox:"0 0 12 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M5.76822 0.359816C5.41466 -0.0644613 4.78409 -0.121785 4.35982 0.231779C3.93554 0.585343 3.87821 1.21591 4.23178 1.64018L5.76822 0.359816ZM10 7L10.7926 7.60971L11.2809 6.97499L10.7682 6.35982L10 7ZM4.20738 12.8903C3.87064 13.328 3.95254 13.9559 4.39029 14.2926C4.82804 14.6294 5.45589 14.5475 5.79262 14.1097L4.20738 12.8903ZM4.23178 1.64018L9.23178 7.64018L10.7682 6.35982L5.76822 0.359816L4.23178 1.64018ZM9.20738 6.39029L4.20738 12.8903L5.79262 14.1097L10.7926 7.60971L9.20738 6.39029Z",fill:"#BDBDBD"}),l("line",{y1:"3.5",x2:"4",y2:"3.5",stroke:"#BDBDBD"}),l("path",{d:"M0 7H4",stroke:"#BDBDBD"}),l("line",{y1:"10.5",x2:"4",y2:"10.5",stroke:"#BDBDBD"})]),l("span",{class:"message"},"Hello log")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#DCBDFB"}},[l("data-lsp",{lsp:"(method) Console.warn(...data: any[]): void"},"warn")]),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello warn'"),l("span",{style:{color:"#ADBAC7"}},")")]),l("div",{class:"meta-line logger warn-log"},[l("svg",{width:"21",height:"18",viewBox:"0 0 21 18",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M9.63401 0.5C10.0189 -0.166667 10.9812 -0.166667 11.3661 0.5L20.4593 16.25C20.8442 16.9167 20.3631 17.75 19.5933 17.75H1.40676C0.636965 17.75 0.15584 16.9167 0.54074 16.25L9.63401 0.5Z",fill:"#E5A604"}),l("rect",{x:"9",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"9",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello warn")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#DCBDFB"}},[l("data-lsp",{lsp:"(method) Console.error(...data: any[]): void"},"error")]),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello error'"),l("span",{style:{color:"#ADBAC7"}},")")]),l("div",{class:"meta-line logger error-log"},[l("svg",{width:"19",height:"19",viewBox:"0 0 19 19",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M4.63018 1.29289L1.29289 4.63018C1.10536 4.81772 1 5.07207 1 5.33729V13.6627C1 13.9279 1.10536 14.1823 1.29289 14.3698L4.63018 17.7071C4.81772 17.8946 5.07207 18 5.33729 18H13.6627C13.9279 18 14.1823 17.8946 14.3698 17.7071L17.7071 14.3698C17.8946 14.1823 18 13.9279 18 13.6627V5.33729C18 5.07207 17.8946 4.81772 17.7071 4.63018L14.3698 1.29289C14.1823 1.10536 13.9279 1 13.6627 1H5.33729C5.07207 1 4.81772 1.10536 4.63018 1.29289Z",fill:"#E72622",stroke:"#E72622"}),l("rect",{x:"8",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"8",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello error")])])])])]),s(` +`),l("div",{class:"tag-container"},[l("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[l("div",{class:"language-id"},"ts"),l("div",{class:"code-container"},[l("code",null,[l("div",{class:"line"},[l("span",{style:{color:"#24292E"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#6F42C1"}},[l("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello log'"),l("span",{style:{color:"#24292E"}},")")]),l("div",{class:"meta-line logger log-log"},[l("svg",{width:"12",height:"15",viewBox:"0 0 12 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M5.76822 0.359816C5.41466 -0.0644613 4.78409 -0.121785 4.35982 0.231779C3.93554 0.585343 3.87821 1.21591 4.23178 1.64018L5.76822 0.359816ZM10 7L10.7926 7.60971L11.2809 6.97499L10.7682 6.35982L10 7ZM4.20738 12.8903C3.87064 13.328 3.95254 13.9559 4.39029 14.2926C4.82804 14.6294 5.45589 14.5475 5.79262 14.1097L4.20738 12.8903ZM4.23178 1.64018L9.23178 7.64018L10.7682 6.35982L5.76822 0.359816L4.23178 1.64018ZM9.20738 6.39029L4.20738 12.8903L5.79262 14.1097L10.7926 7.60971L9.20738 6.39029Z",fill:"#BDBDBD"}),l("line",{y1:"3.5",x2:"4",y2:"3.5",stroke:"#BDBDBD"}),l("path",{d:"M0 7H4",stroke:"#BDBDBD"}),l("line",{y1:"10.5",x2:"4",y2:"10.5",stroke:"#BDBDBD"})]),l("span",{class:"message"},"Hello log")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#24292E"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#6F42C1"}},[l("data-lsp",{lsp:"(method) Console.warn(...data: any[]): void"},"warn")]),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello warn'"),l("span",{style:{color:"#24292E"}},")")]),l("div",{class:"meta-line logger warn-log"},[l("svg",{width:"21",height:"18",viewBox:"0 0 21 18",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M9.63401 0.5C10.0189 -0.166667 10.9812 -0.166667 11.3661 0.5L20.4593 16.25C20.8442 16.9167 20.3631 17.75 19.5933 17.75H1.40676C0.636965 17.75 0.15584 16.9167 0.54074 16.25L9.63401 0.5Z",fill:"#E5A604"}),l("rect",{x:"9",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"9",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello warn")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#24292E"}},[l("data-lsp",{lsp:"var console: Console"},"console"),s(".")]),l("span",{style:{color:"#6F42C1"}},[l("data-lsp",{lsp:"(method) Console.error(...data: any[]): void"},"error")]),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello error'"),l("span",{style:{color:"#24292E"}},")")]),l("div",{class:"meta-line logger error-log"},[l("svg",{width:"19",height:"19",viewBox:"0 0 19 19",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M4.63018 1.29289L1.29289 4.63018C1.10536 4.81772 1 5.07207 1 5.33729V13.6627C1 13.9279 1.10536 14.1823 1.29289 14.3698L4.63018 17.7071C4.81772 17.8946 5.07207 18 5.33729 18H13.6627C13.9279 18 14.1823 17.8946 14.3698 17.7071L17.7071 14.3698C17.8946 14.1823 18 13.9279 18 13.6627V5.33729C18 5.07207 17.8946 4.81772 17.7071 4.63018L14.3698 1.29289C14.1823 1.10536 13.9279 1 13.6627 1H5.33729C5.07207 1 4.81772 1.10536 4.63018 1.29289Z",fill:"#E72622",stroke:"#E72622"}),l("rect",{x:"8",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"8",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello error")])])])])])])]),l("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[l("span",{class:"line-number"},"1"),l("br")])]),l("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[l("button",{title:"Copy Code",class:"copy"}),l("span",{class:"lang"},"md"),l("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[l("code",null,[l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"console."),l("span",{style:{color:"#DCBDFB"}},"log"),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello log'"),l("span",{style:{color:"#ADBAC7"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#768390"}},"// @log: Hello log")]),s(` +`),l("span",{class:"line"}),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"console."),l("span",{style:{color:"#DCBDFB"}},"warn"),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello warn'"),l("span",{style:{color:"#ADBAC7"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#768390"}},"// @warn: Hello warn")]),s(` +`),l("span",{class:"line"}),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"console."),l("span",{style:{color:"#DCBDFB"}},"error"),l("span",{style:{color:"#ADBAC7"}},"("),l("span",{style:{color:"#96D0FF"}},"'Hello error'"),l("span",{style:{color:"#ADBAC7"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#768390"}},"// @error: Hello error")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#ADBAC7"}},"```")])])]),l("pre",{class:"shiki github-light vp-code-light"},[l("code",null,[l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"```ts twoslash")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"console."),l("span",{style:{color:"#6F42C1"}},"log"),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello log'"),l("span",{style:{color:"#24292E"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#6A737D"}},"// @log: Hello log")]),s(` +`),l("span",{class:"line"}),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"console."),l("span",{style:{color:"#6F42C1"}},"warn"),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello warn'"),l("span",{style:{color:"#24292E"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#6A737D"}},"// @warn: Hello warn")]),s(` +`),l("span",{class:"line"}),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"console."),l("span",{style:{color:"#6F42C1"}},"error"),l("span",{style:{color:"#24292E"}},"("),l("span",{style:{color:"#032F62"}},"'Hello error'"),l("span",{style:{color:"#24292E"}},")")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#6A737D"}},"// @error: Hello error")]),s(` +`),l("span",{class:"line"},[l("span",{style:{color:"#24292E"}},"```")])])]),l("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[l("span",{class:"line-number"},"1"),l("br"),l("span",{class:"line-number"},"2"),l("br"),l("span",{class:"line-number"},"3"),l("br"),l("span",{class:"line-number"},"4"),l("br"),l("span",{class:"line-number"},"5"),l("br"),l("span",{class:"line-number"},"6"),l("br"),l("span",{class:"line-number"},"7"),l("br"),l("span",{class:"line-number"},"8"),l("br"),l("span",{class:"line-number"},"9"),l("br"),l("span",{class:"line-number"},"10"),l("br")])])])],-1);function h(y,w,m,C,v,u){const e=o;return n(),t("div",null,[p,r(e,{readTime:"1",words:"152"}),d,g])}const A=a(c,[["render",h]]);export{f as __pageData,A as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.d3641bab.js b/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.d3641bab.js deleted file mode 100644 index 3e9226b7..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.d3641bab.js +++ /dev/null @@ -1,20 +0,0 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as r,k as l,a as s,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Logging","description":"Display formatted output for code examples.","frontmatter":{"description":"Display formatted output for code examples.","title":"Logging","keywords":["console","javascript","typescript","showcase","snippets"]},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/logging.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/logging.md","lastUpdated":1695377563000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/logging.md"},p=l("h1",{id:"logging",tabindex:"-1"},[s("Logging "),l("a",{class:"header-anchor",href:"#logging","aria-label":'Permalink to "Logging"'},"​")],-1),d=i('

    When you first see a Twoslash code example with an inline compiler error, you instinctively trust that the compiler error is correct because the design shows that it is not a part of the code sample. The logging tools lets you do that, but abuses the systemic trust because your code is not being evaluated to generate the logs.

    This feature is effectively a facade, people will trust your output and it will look better.

    @log:, @warn:, @error:

    The names are based on the functions on the console object:

    ',4),g=l("div",{class:"vp-code-group vp-adaptive-theme"},[l("div",{class:"tabs"},[l("input",{type:"radio",name:"group-FCfwU",id:"tab-3NifHbL",checked:"checked"}),l("label",{for:"tab-3NifHbL"},"output"),l("input",{type:"radio",name:"group-FCfwU",id:"tab-y9JwiF_"}),l("label",{for:"tab-y9JwiF_"},"markdown")]),l("div",{class:"blocks"},[l("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[l("button",{title:"Copy Code",class:"copy"}),l("span",{class:"lang"},"ts"),l("pre",null,[l("code",{class:"language-ts"},[l("div",{class:"tag-container"},[l("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[l("div",{class:"language-id"},"ts"),l("div",{class:"code-container"},[l("code",null,[l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello log'"),l("span",{style:{color:"#839496"}},")")]),l("div",{class:"meta-line logger log-log"},[l("svg",{width:"12",height:"15",viewBox:"0 0 12 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M5.76822 0.359816C5.41466 -0.0644613 4.78409 -0.121785 4.35982 0.231779C3.93554 0.585343 3.87821 1.21591 4.23178 1.64018L5.76822 0.359816ZM10 7L10.7926 7.60971L11.2809 6.97499L10.7682 6.35982L10 7ZM4.20738 12.8903C3.87064 13.328 3.95254 13.9559 4.39029 14.2926C4.82804 14.6294 5.45589 14.5475 5.79262 14.1097L4.20738 12.8903ZM4.23178 1.64018L9.23178 7.64018L10.7682 6.35982L5.76822 0.359816L4.23178 1.64018ZM9.20738 6.39029L4.20738 12.8903L5.79262 14.1097L10.7926 7.60971L9.20738 6.39029Z",fill:"#BDBDBD"}),l("line",{y1:"3.5",x2:"4",y2:"3.5",stroke:"#BDBDBD"}),l("path",{d:"M0 7H4",stroke:"#BDBDBD"}),l("line",{y1:"10.5",x2:"4",y2:"10.5",stroke:"#BDBDBD"})]),l("span",{class:"message"},"Hello log")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.warn(...data: any[]): void"},"warn")]),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello warn'"),l("span",{style:{color:"#839496"}},")")]),l("div",{class:"meta-line logger warn-log"},[l("svg",{width:"21",height:"18",viewBox:"0 0 21 18",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M9.63401 0.5C10.0189 -0.166667 10.9812 -0.166667 11.3661 0.5L20.4593 16.25C20.8442 16.9167 20.3631 17.75 19.5933 17.75H1.40676C0.636965 17.75 0.15584 16.9167 0.54074 16.25L9.63401 0.5Z",fill:"#E5A604"}),l("rect",{x:"9",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"9",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello warn")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.error(...data: any[]): void"},"error")]),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello error'"),l("span",{style:{color:"#839496"}},")")]),l("div",{class:"meta-line logger error-log"},[l("svg",{width:"19",height:"19",viewBox:"0 0 19 19",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M4.63018 1.29289L1.29289 4.63018C1.10536 4.81772 1 5.07207 1 5.33729V13.6627C1 13.9279 1.10536 14.1823 1.29289 14.3698L4.63018 17.7071C4.81772 17.8946 5.07207 18 5.33729 18H13.6627C13.9279 18 14.1823 17.8946 14.3698 17.7071L17.7071 14.3698C17.8946 14.1823 18 13.9279 18 13.6627V5.33729C18 5.07207 17.8946 4.81772 17.7071 4.63018L14.3698 1.29289C14.1823 1.10536 13.9279 1 13.6627 1H5.33729C5.07207 1 4.81772 1.10536 4.63018 1.29289Z",fill:"#E72622",stroke:"#E72622"}),l("rect",{x:"8",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"8",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello error")])])])])]),s(` -`),l("div",{class:"tag-container"},[l("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[l("div",{class:"language-id"},"ts"),l("div",{class:"code-container"},[l("code",null,[l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello log'"),l("span",{style:{color:"#657B83"}},")")]),l("div",{class:"meta-line logger log-log"},[l("svg",{width:"12",height:"15",viewBox:"0 0 12 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M5.76822 0.359816C5.41466 -0.0644613 4.78409 -0.121785 4.35982 0.231779C3.93554 0.585343 3.87821 1.21591 4.23178 1.64018L5.76822 0.359816ZM10 7L10.7926 7.60971L11.2809 6.97499L10.7682 6.35982L10 7ZM4.20738 12.8903C3.87064 13.328 3.95254 13.9559 4.39029 14.2926C4.82804 14.6294 5.45589 14.5475 5.79262 14.1097L4.20738 12.8903ZM4.23178 1.64018L9.23178 7.64018L10.7682 6.35982L5.76822 0.359816L4.23178 1.64018ZM9.20738 6.39029L4.20738 12.8903L5.79262 14.1097L10.7926 7.60971L9.20738 6.39029Z",fill:"#BDBDBD"}),l("line",{y1:"3.5",x2:"4",y2:"3.5",stroke:"#BDBDBD"}),l("path",{d:"M0 7H4",stroke:"#BDBDBD"}),l("line",{y1:"10.5",x2:"4",y2:"10.5",stroke:"#BDBDBD"})]),l("span",{class:"message"},"Hello log")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.warn(...data: any[]): void"},"warn")]),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello warn'"),l("span",{style:{color:"#657B83"}},")")]),l("div",{class:"meta-line logger warn-log"},[l("svg",{width:"21",height:"18",viewBox:"0 0 21 18",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M9.63401 0.5C10.0189 -0.166667 10.9812 -0.166667 11.3661 0.5L20.4593 16.25C20.8442 16.9167 20.3631 17.75 19.5933 17.75H1.40676C0.636965 17.75 0.15584 16.9167 0.54074 16.25L9.63401 0.5Z",fill:"#E5A604"}),l("rect",{x:"9",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"9",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello warn")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.error(...data: any[]): void"},"error")]),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello error'"),l("span",{style:{color:"#657B83"}},")")]),l("div",{class:"meta-line logger error-log"},[l("svg",{width:"19",height:"19",viewBox:"0 0 19 19",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M4.63018 1.29289L1.29289 4.63018C1.10536 4.81772 1 5.07207 1 5.33729V13.6627C1 13.9279 1.10536 14.1823 1.29289 14.3698L4.63018 17.7071C4.81772 17.8946 5.07207 18 5.33729 18H13.6627C13.9279 18 14.1823 17.8946 14.3698 17.7071L17.7071 14.3698C17.8946 14.1823 18 13.9279 18 13.6627V5.33729C18 5.07207 17.8946 4.81772 17.7071 4.63018L14.3698 1.29289C14.1823 1.10536 13.9279 1 13.6627 1H5.33729C5.07207 1 4.81772 1.10536 4.63018 1.29289Z",fill:"#E72622",stroke:"#E72622"}),l("rect",{x:"8",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"8",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello error")])])])])])])]),l("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[l("span",{class:"line-number"},"1"),l("br")])]),l("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[l("button",{title:"Copy Code",class:"copy"}),l("span",{class:"lang"},"md"),l("pre",{class:"shiki solarized-dark vp-code-dark"},[l("code",null,[l("span",{class:"line"},[l("span",{style:{color:"#839496"}},"```ts twoslash")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},"log"),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello log'"),l("span",{style:{color:"#839496"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#586E75","font-style":"italic"}},"// @log: Hello log")]),s(` -`),l("span",{class:"line"}),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},"warn"),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello warn'"),l("span",{style:{color:"#839496"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#586E75","font-style":"italic"}},"// @warn: Hello warn")]),s(` -`),l("span",{class:"line"}),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},"error"),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello error'"),l("span",{style:{color:"#839496"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#586E75","font-style":"italic"}},"// @error: Hello error")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#839496"}},"```")])])]),l("pre",{class:"shiki solarized-light vp-code-light"},[l("code",null,[l("span",{class:"line"},[l("span",{style:{color:"#657B83"}},"```ts twoslash")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},"log"),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello log'"),l("span",{style:{color:"#657B83"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @log: Hello log")]),s(` -`),l("span",{class:"line"}),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},"warn"),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello warn'"),l("span",{style:{color:"#657B83"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @warn: Hello warn")]),s(` -`),l("span",{class:"line"}),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},"error"),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello error'"),l("span",{style:{color:"#657B83"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @error: Hello error")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#657B83"}},"```")])])]),l("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[l("span",{class:"line-number"},"1"),l("br"),l("span",{class:"line-number"},"2"),l("br"),l("span",{class:"line-number"},"3"),l("br"),l("span",{class:"line-number"},"4"),l("br"),l("span",{class:"line-number"},"5"),l("br"),l("span",{class:"line-number"},"6"),l("br"),l("span",{class:"line-number"},"7"),l("br"),l("span",{class:"line-number"},"8"),l("br"),l("span",{class:"line-number"},"9"),l("br"),l("span",{class:"line-number"},"10"),l("br")])])])],-1);function y(h,w,B,v,m,u){const e=o;return n(),t("div",null,[p,r(e,{readTime:"1",words:"152"}),d,g])}const L=a(c,[["render",y]]);export{C as __pageData,L as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.d3641bab.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.d3641bab.lean.js deleted file mode 100644 index 79dc3672..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_logging.md.d3641bab.lean.js +++ /dev/null @@ -1,20 +0,0 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as r,k as l,a as s,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Logging","description":"Display formatted output for code examples.","frontmatter":{"description":"Display formatted output for code examples.","title":"Logging","keywords":["console","javascript","typescript","showcase","snippets"]},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/logging.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/logging.md","lastUpdated":1695377563000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/logging.md"},p=l("h1",{id:"logging",tabindex:"-1"},[s("Logging "),l("a",{class:"header-anchor",href:"#logging","aria-label":'Permalink to "Logging"'},"​")],-1),d=i("",4),g=l("div",{class:"vp-code-group vp-adaptive-theme"},[l("div",{class:"tabs"},[l("input",{type:"radio",name:"group-FCfwU",id:"tab-3NifHbL",checked:"checked"}),l("label",{for:"tab-3NifHbL"},"output"),l("input",{type:"radio",name:"group-FCfwU",id:"tab-y9JwiF_"}),l("label",{for:"tab-y9JwiF_"},"markdown")]),l("div",{class:"blocks"},[l("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[l("button",{title:"Copy Code",class:"copy"}),l("span",{class:"lang"},"ts"),l("pre",null,[l("code",{class:"language-ts"},[l("div",{class:"tag-container"},[l("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[l("div",{class:"language-id"},"ts"),l("div",{class:"code-container"},[l("code",null,[l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello log'"),l("span",{style:{color:"#839496"}},")")]),l("div",{class:"meta-line logger log-log"},[l("svg",{width:"12",height:"15",viewBox:"0 0 12 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M5.76822 0.359816C5.41466 -0.0644613 4.78409 -0.121785 4.35982 0.231779C3.93554 0.585343 3.87821 1.21591 4.23178 1.64018L5.76822 0.359816ZM10 7L10.7926 7.60971L11.2809 6.97499L10.7682 6.35982L10 7ZM4.20738 12.8903C3.87064 13.328 3.95254 13.9559 4.39029 14.2926C4.82804 14.6294 5.45589 14.5475 5.79262 14.1097L4.20738 12.8903ZM4.23178 1.64018L9.23178 7.64018L10.7682 6.35982L5.76822 0.359816L4.23178 1.64018ZM9.20738 6.39029L4.20738 12.8903L5.79262 14.1097L10.7926 7.60971L9.20738 6.39029Z",fill:"#BDBDBD"}),l("line",{y1:"3.5",x2:"4",y2:"3.5",stroke:"#BDBDBD"}),l("path",{d:"M0 7H4",stroke:"#BDBDBD"}),l("line",{y1:"10.5",x2:"4",y2:"10.5",stroke:"#BDBDBD"})]),l("span",{class:"message"},"Hello log")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.warn(...data: any[]): void"},"warn")]),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello warn'"),l("span",{style:{color:"#839496"}},")")]),l("div",{class:"meta-line logger warn-log"},[l("svg",{width:"21",height:"18",viewBox:"0 0 21 18",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M9.63401 0.5C10.0189 -0.166667 10.9812 -0.166667 11.3661 0.5L20.4593 16.25C20.8442 16.9167 20.3631 17.75 19.5933 17.75H1.40676C0.636965 17.75 0.15584 16.9167 0.54074 16.25L9.63401 0.5Z",fill:"#E5A604"}),l("rect",{x:"9",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"9",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello warn")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.error(...data: any[]): void"},"error")]),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello error'"),l("span",{style:{color:"#839496"}},")")]),l("div",{class:"meta-line logger error-log"},[l("svg",{width:"19",height:"19",viewBox:"0 0 19 19",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M4.63018 1.29289L1.29289 4.63018C1.10536 4.81772 1 5.07207 1 5.33729V13.6627C1 13.9279 1.10536 14.1823 1.29289 14.3698L4.63018 17.7071C4.81772 17.8946 5.07207 18 5.33729 18H13.6627C13.9279 18 14.1823 17.8946 14.3698 17.7071L17.7071 14.3698C17.8946 14.1823 18 13.9279 18 13.6627V5.33729C18 5.07207 17.8946 4.81772 17.7071 4.63018L14.3698 1.29289C14.1823 1.10536 13.9279 1 13.6627 1H5.33729C5.07207 1 4.81772 1.10536 4.63018 1.29289Z",fill:"#E72622",stroke:"#E72622"}),l("rect",{x:"8",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"8",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello error")])])])])]),s(` -`),l("div",{class:"tag-container"},[l("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[l("div",{class:"language-id"},"ts"),l("div",{class:"code-container"},[l("code",null,[l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello log'"),l("span",{style:{color:"#657B83"}},")")]),l("div",{class:"meta-line logger log-log"},[l("svg",{width:"12",height:"15",viewBox:"0 0 12 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M5.76822 0.359816C5.41466 -0.0644613 4.78409 -0.121785 4.35982 0.231779C3.93554 0.585343 3.87821 1.21591 4.23178 1.64018L5.76822 0.359816ZM10 7L10.7926 7.60971L11.2809 6.97499L10.7682 6.35982L10 7ZM4.20738 12.8903C3.87064 13.328 3.95254 13.9559 4.39029 14.2926C4.82804 14.6294 5.45589 14.5475 5.79262 14.1097L4.20738 12.8903ZM4.23178 1.64018L9.23178 7.64018L10.7682 6.35982L5.76822 0.359816L4.23178 1.64018ZM9.20738 6.39029L4.20738 12.8903L5.79262 14.1097L10.7926 7.60971L9.20738 6.39029Z",fill:"#BDBDBD"}),l("line",{y1:"3.5",x2:"4",y2:"3.5",stroke:"#BDBDBD"}),l("path",{d:"M0 7H4",stroke:"#BDBDBD"}),l("line",{y1:"10.5",x2:"4",y2:"10.5",stroke:"#BDBDBD"})]),l("span",{class:"message"},"Hello log")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.warn(...data: any[]): void"},"warn")]),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello warn'"),l("span",{style:{color:"#657B83"}},")")]),l("div",{class:"meta-line logger warn-log"},[l("svg",{width:"21",height:"18",viewBox:"0 0 21 18",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M9.63401 0.5C10.0189 -0.166667 10.9812 -0.166667 11.3661 0.5L20.4593 16.25C20.8442 16.9167 20.3631 17.75 19.5933 17.75H1.40676C0.636965 17.75 0.15584 16.9167 0.54074 16.25L9.63401 0.5Z",fill:"#E5A604"}),l("rect",{x:"9",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"9",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello warn")]),l("div",{class:"line"}," "),l("div",{class:"line"},[l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"var console: Console"},"console")]),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},[l("data-lsp",{lsp:"(method) Console.error(...data: any[]): void"},"error")]),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello error'"),l("span",{style:{color:"#657B83"}},")")]),l("div",{class:"meta-line logger error-log"},[l("svg",{width:"19",height:"19",viewBox:"0 0 19 19",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[l("path",{d:"M4.63018 1.29289L1.29289 4.63018C1.10536 4.81772 1 5.07207 1 5.33729V13.6627C1 13.9279 1.10536 14.1823 1.29289 14.3698L4.63018 17.7071C4.81772 17.8946 5.07207 18 5.33729 18H13.6627C13.9279 18 14.1823 17.8946 14.3698 17.7071L17.7071 14.3698C17.8946 14.1823 18 13.9279 18 13.6627V5.33729C18 5.07207 17.8946 4.81772 17.7071 4.63018L14.3698 1.29289C14.1823 1.10536 13.9279 1 13.6627 1H5.33729C5.07207 1 4.81772 1.10536 4.63018 1.29289Z",fill:"#E72622",stroke:"#E72622"}),l("rect",{x:"8",y:"4",width:"3",height:"7",fill:"white"}),l("rect",{x:"8",y:"13",width:"3",height:"3",fill:"white"})]),l("span",{class:"message"},"Hello error")])])])])])])]),l("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[l("span",{class:"line-number"},"1"),l("br")])]),l("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[l("button",{title:"Copy Code",class:"copy"}),l("span",{class:"lang"},"md"),l("pre",{class:"shiki solarized-dark vp-code-dark"},[l("code",null,[l("span",{class:"line"},[l("span",{style:{color:"#839496"}},"```ts twoslash")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},"log"),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello log'"),l("span",{style:{color:"#839496"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#586E75","font-style":"italic"}},"// @log: Hello log")]),s(` -`),l("span",{class:"line"}),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},"warn"),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello warn'"),l("span",{style:{color:"#839496"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#586E75","font-style":"italic"}},"// @warn: Hello warn")]),s(` -`),l("span",{class:"line"}),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#839496"}},"."),l("span",{style:{color:"#268BD2"}},"error"),l("span",{style:{color:"#839496"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello error'"),l("span",{style:{color:"#839496"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#586E75","font-style":"italic"}},"// @error: Hello error")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#839496"}},"```")])])]),l("pre",{class:"shiki solarized-light vp-code-light"},[l("code",null,[l("span",{class:"line"},[l("span",{style:{color:"#657B83"}},"```ts twoslash")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},"log"),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello log'"),l("span",{style:{color:"#657B83"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @log: Hello log")]),s(` -`),l("span",{class:"line"}),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},"warn"),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello warn'"),l("span",{style:{color:"#657B83"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @warn: Hello warn")]),s(` -`),l("span",{class:"line"}),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#268BD2"}},"console"),l("span",{style:{color:"#657B83"}},"."),l("span",{style:{color:"#268BD2"}},"error"),l("span",{style:{color:"#657B83"}},"("),l("span",{style:{color:"#2AA198"}},"'Hello error'"),l("span",{style:{color:"#657B83"}},")")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @error: Hello error")]),s(` -`),l("span",{class:"line"},[l("span",{style:{color:"#657B83"}},"```")])])]),l("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[l("span",{class:"line-number"},"1"),l("br"),l("span",{class:"line-number"},"2"),l("br"),l("span",{class:"line-number"},"3"),l("br"),l("span",{class:"line-number"},"4"),l("br"),l("span",{class:"line-number"},"5"),l("br"),l("span",{class:"line-number"},"6"),l("br"),l("span",{class:"line-number"},"7"),l("br"),l("span",{class:"line-number"},"8"),l("br"),l("span",{class:"line-number"},"9"),l("br"),l("span",{class:"line-number"},"10"),l("br")])])])],-1);function y(h,w,B,v,m,u){const e=o;return n(),t("div",null,[p,r(e,{readTime:"1",words:"152"}),d,g])}const L=a(c,[["render",y]]);export{C as __pageData,L as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.48f61f4c.js b/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.48f61f4c.js new file mode 100644 index 00000000..a2c2f578 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.48f61f4c.js @@ -0,0 +1,71 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o,c as t,H as i,k as s,a as l,Q as p}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const B=JSON.parse(`{"title":"Multi-file","description":"Twoslash code examples aren't limited to creating a single file. You can write any file to the virtual file system used by TypeScript to power your code examples.","frontmatter":{"description":"Twoslash code examples aren't limited to creating a single file. You can write any file to the virtual file system used by TypeScript to power your code examples.","title":"Multi-file"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/multi-file.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/multi-file.md","lastUpdated":1699051935000}`),c={name:"application/vitepress-plugin-shiki-twoslash/api/multi-file.md"},r=s("h1",{id:"multi-file",tabindex:"-1"},[l("Multi-file "),s("a",{class:"header-anchor",href:"#multi-file","aria-label":'Permalink to "Multi-file"'},"​")],-1),d=p('

    Twoslash code examples aren't limited to creating a single file, by using // @filename: [file] you can write any file to the virtual file system used by TypeScript to power your code examples.

    @filename: [file]

    Most of the time, you don't need to think about the underlaying virtual file system in a code example, but when you have imports between them it becomes important to know. Twoslash will default to creating an index.[type] based on the langauge passed to the code example:

    ts
    ts
    // I'm index.ts
    ts
    // I'm index.ts
    md
    ```ts twoslash\n// I'm index.ts\n```
    ```ts twoslash\n// I'm index.ts\n```
    tsx
    tsx
    // I'm index.tsx
    tsx
    // I'm index.tsx
    md
    ```tsx twoslash\n// I'm index.tsx\n```
    ```tsx twoslash\n// I'm index.tsx\n```
    js
    js
    // I'm index.tjs
    js
    // I'm index.tjs
    md
    ```js twoslash\n// I'm index.tjs\n```
    ```js twoslash\n// I'm index.tjs\n```

    Then until Twoslash hits another // @filename: [file], the parser keeps adding new lines into the same file. After seeing @filename Twoslash creates a new virtual file-system file and adds the new lines to that. You can't edit a file after it was created, but you can overwrite it.

    It can be any file. For example, if you want to quickly fake a node module:

    ',8),y=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-ovkmV",id:"tab-d56pGM1",checked:"checked"}),s("label",{for:"tab-d56pGM1"},"output"),s("input",{type:"radio",name:"group-ovkmV",id:"tab-hEQfy3G"}),s("label",{for:"tab-hEQfy3G"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function doit(): string"},"doit")]),s("span",{style:{color:"#ADBAC7"}},"()"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function doit(): string +import doit`},"doit"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'mylib'")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#ADBAC7"}},[l("("),s("data-lsp",{lsp:`(alias) function doit(): string +import doit`},"doit"),l(")")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function doit(): string"},"doit")]),s("span",{style:{color:"#24292E"}},"()"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function doit(): string +import doit`},"doit"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'mylib'")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#24292E"}},[l("("),s("data-lsp",{lsp:`(alias) function doit(): string +import doit`},"doit"),l(")")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("p",null,"This code example sets up the types for a non-existent npm module, and TypeScript picks it up as the definitions in the same way it would in a non-virtual TypeScript project."),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"doit"),s("span",{style:{color:"#ADBAC7"}},"()"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," { doit } "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'mylib'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"console."),s("span",{style:{color:"#DCBDFB"}},"log"),s("span",{style:{color:"#ADBAC7"}},"(doit)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"doit"),s("span",{style:{color:"#24292E"}},"()"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," { doit } "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'mylib'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"console."),s("span",{style:{color:"#6F42C1"}},"log"),s("span",{style:{color:"#24292E"}},"(doit)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br")])])])],-1),m=s("p",null,"You can also set up a JSON object which can be imported in a TypeScript file:",-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-81pvk",id:"tab-6qtDygM",checked:"checked"}),s("label",{for:"tab-6qtDygM"},"output"),s("input",{type:"radio",name:"group-81pvk",id:"tab-cm-U88T"}),s("label",{for:"tab-cm-U88T"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: app.json")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"{ "),s("span",{style:{color:"#96D0FF"}},'"version"'),s("span",{style:{color:"#ADBAC7"}},": "),s("span",{style:{color:"#96D0FF"}},'"23.2.3"'),s("span",{style:{color:"#ADBAC7"}}," }")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:"import appSettings"},"appSettings"),l()]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"./app.json"')]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings"),l("."),s("data-lsp",{lsp:'(property) "version": string',style:{"border-bottom":"solid 2px lightgrey"}},"version")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l('(property) "version": string')])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: app.json")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"{ "),s("span",{style:{color:"#032F62"}},'"version"'),s("span",{style:{color:"#24292E"}},": "),s("span",{style:{color:"#032F62"}},'"23.2.3"'),s("span",{style:{color:"#24292E"}}," }")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:"import appSettings"},"appSettings"),l()]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"./app.json"')]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings"),l("."),s("data-lsp",{lsp:'(property) "version": string',style:{"border-bottom":"solid 2px lightgrey"}},"version")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l('(property) "version": string')])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @resolveJsonModule")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: app.json")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"{ "),s("span",{style:{color:"#96D0FF"}},'"version"'),s("span",{style:{color:"#ADBAC7"}},": "),s("span",{style:{color:"#96D0FF"}},'"23.2.3"'),s("span",{style:{color:"#ADBAC7"}}," }")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," appSettings "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"./app.json"')]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"appSettings.version")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @resolveJsonModule")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: app.json")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"{ "),s("span",{style:{color:"#032F62"}},'"version"'),s("span",{style:{color:"#24292E"}},": "),s("span",{style:{color:"#032F62"}},'"23.2.3"'),s("span",{style:{color:"#24292E"}}," }")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," appSettings "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"./app.json"')]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"appSettings.version")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br")])])])],-1),b=s("p",null,[l("Finally, the following code allows importing non-TypeScript content. There is a "),s("code",null,".d.ts"),l(` file which globally says 'md files are OK to import' and 'the module "react" exists, but don't worry about the details'.`)],-1),v=s("p",null,[l("Then for a user, they only see the imports and exports inside "),s("code",null,"index.tsx"),l(".")],-1),h=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-e0qGQ",id:"tab-1-8u2qz",checked:"checked"}),s("label",{for:"tab-1-8u2qz"},"output"),s("input",{type:"radio",name:"group-e0qGQ",id:"tab-EvdxuJW"}),s("label",{for:"tab-EvdxuJW"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:`(alias) module "react" +import React`},"React"),l()]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"react"')]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs"),l()]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"./MultiFileDocs.mdx"')]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#F69D50"}},[l(" <"),s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs"),l("/>")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:`(alias) module "react" +import React`},"React"),l()]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"react"')]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs"),l()]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"./MultiFileDocs.mdx"')]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#24292E"}},"/>")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: ambient.d.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"declare"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"module"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'*.mdx'"),s("span",{style:{color:"#ADBAC7"}}," {")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},"any")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"declare"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"module"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"react"')]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: MultiFileDocs.mdx")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"## "),s("span",{style:{color:"#F69D50"}},"Hello"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"world")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.tsx")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," React "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"react"')]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," MultiFileDocs "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"./MultiFileDocs.mdx"')]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#F69D50"}}," ")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: ambient.d.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"declare"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"module"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'*.mdx'"),s("span",{style:{color:"#24292E"}}," {")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," any")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"declare"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"module"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"react"')]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: MultiFileDocs.mdx")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"## "),s("span",{style:{color:"#6F42C1"}},"Hello"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"world")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.tsx")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," React "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"react"')]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," MultiFileDocs "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"./MultiFileDocs.mdx"')]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#6F42C1"}},"MultiFileDocs"),s("span",{style:{color:"#24292E"}},"/>")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br"),s("span",{class:"line-number"},"15"),s("br"),s("span",{class:"line-number"},"16"),s("br"),s("span",{class:"line-number"},"17"),s("br")])])])],-1);function g(A,D,f,F,C,k){const e=a;return o(),t("div",null,[r,i(e,{readTime:"2",words:"477"}),d,y,m,u,b,v,h])}const _=n(c,[["render",g]]);export{B as __pageData,_ as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.48f61f4c.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.48f61f4c.lean.js new file mode 100644 index 00000000..c74a820f --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.48f61f4c.lean.js @@ -0,0 +1,71 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o,c as t,H as i,k as s,a as l,Q as p}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const B=JSON.parse(`{"title":"Multi-file","description":"Twoslash code examples aren't limited to creating a single file. You can write any file to the virtual file system used by TypeScript to power your code examples.","frontmatter":{"description":"Twoslash code examples aren't limited to creating a single file. You can write any file to the virtual file system used by TypeScript to power your code examples.","title":"Multi-file"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/multi-file.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/multi-file.md","lastUpdated":1699051935000}`),c={name:"application/vitepress-plugin-shiki-twoslash/api/multi-file.md"},r=s("h1",{id:"multi-file",tabindex:"-1"},[l("Multi-file "),s("a",{class:"header-anchor",href:"#multi-file","aria-label":'Permalink to "Multi-file"'},"​")],-1),d=p("",8),y=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-ovkmV",id:"tab-d56pGM1",checked:"checked"}),s("label",{for:"tab-d56pGM1"},"output"),s("input",{type:"radio",name:"group-ovkmV",id:"tab-hEQfy3G"}),s("label",{for:"tab-hEQfy3G"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function doit(): string"},"doit")]),s("span",{style:{color:"#ADBAC7"}},"()"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function doit(): string +import doit`},"doit"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'mylib'")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#ADBAC7"}},[l("("),s("data-lsp",{lsp:`(alias) function doit(): string +import doit`},"doit"),l(")")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function doit(): string"},"doit")]),s("span",{style:{color:"#24292E"}},"()"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function doit(): string +import doit`},"doit"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'mylib'")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l(".")]),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#24292E"}},[l("("),s("data-lsp",{lsp:`(alias) function doit(): string +import doit`},"doit"),l(")")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("p",null,"This code example sets up the types for a non-existent npm module, and TypeScript picks it up as the definitions in the same way it would in a non-virtual TypeScript project."),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"doit"),s("span",{style:{color:"#ADBAC7"}},"()"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," { doit } "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'mylib'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"console."),s("span",{style:{color:"#DCBDFB"}},"log"),s("span",{style:{color:"#ADBAC7"}},"(doit)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"doit"),s("span",{style:{color:"#24292E"}},"()"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," { doit } "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'mylib'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"console."),s("span",{style:{color:"#6F42C1"}},"log"),s("span",{style:{color:"#24292E"}},"(doit)")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br")])])])],-1),m=s("p",null,"You can also set up a JSON object which can be imported in a TypeScript file:",-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-81pvk",id:"tab-6qtDygM",checked:"checked"}),s("label",{for:"tab-6qtDygM"},"output"),s("input",{type:"radio",name:"group-81pvk",id:"tab-cm-U88T"}),s("label",{for:"tab-cm-U88T"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: app.json")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"{ "),s("span",{style:{color:"#96D0FF"}},'"version"'),s("span",{style:{color:"#ADBAC7"}},": "),s("span",{style:{color:"#96D0FF"}},'"23.2.3"'),s("span",{style:{color:"#ADBAC7"}}," }")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:"import appSettings"},"appSettings"),l()]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"./app.json"')]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings"),l("."),s("data-lsp",{lsp:'(property) "version": string',style:{"border-bottom":"solid 2px lightgrey"}},"version")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l('(property) "version": string')])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: app.json")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"{ "),s("span",{style:{color:"#032F62"}},'"version"'),s("span",{style:{color:"#24292E"}},": "),s("span",{style:{color:"#032F62"}},'"23.2.3"'),s("span",{style:{color:"#24292E"}}," }")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:"import appSettings"},"appSettings"),l()]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"./app.json"')]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings"),l("."),s("data-lsp",{lsp:'(property) "version": string',style:{"border-bottom":"solid 2px lightgrey"}},"version")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l('(property) "version": string')])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @resolveJsonModule")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: app.json")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"{ "),s("span",{style:{color:"#96D0FF"}},'"version"'),s("span",{style:{color:"#ADBAC7"}},": "),s("span",{style:{color:"#96D0FF"}},'"23.2.3"'),s("span",{style:{color:"#ADBAC7"}}," }")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," appSettings "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"./app.json"')]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"appSettings.version")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @resolveJsonModule")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: app.json")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"{ "),s("span",{style:{color:"#032F62"}},'"version"'),s("span",{style:{color:"#24292E"}},": "),s("span",{style:{color:"#032F62"}},'"23.2.3"'),s("span",{style:{color:"#24292E"}}," }")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," appSettings "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"./app.json"')]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"appSettings.version")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br")])])])],-1),b=s("p",null,[l("Finally, the following code allows importing non-TypeScript content. There is a "),s("code",null,".d.ts"),l(` file which globally says 'md files are OK to import' and 'the module "react" exists, but don't worry about the details'.`)],-1),v=s("p",null,[l("Then for a user, they only see the imports and exports inside "),s("code",null,"index.tsx"),l(".")],-1),h=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-e0qGQ",id:"tab-1-8u2qz",checked:"checked"}),s("label",{for:"tab-1-8u2qz"},"output"),s("input",{type:"radio",name:"group-e0qGQ",id:"tab-EvdxuJW"}),s("label",{for:"tab-EvdxuJW"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:`(alias) module "react" +import React`},"React"),l()]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"react"')]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs"),l()]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"./MultiFileDocs.mdx"')]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#F69D50"}},[l(" <"),s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs"),l("/>")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:`(alias) module "react" +import React`},"React"),l()]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"react"')]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs"),l()]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"./MultiFileDocs.mdx"')]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#24292E"}},"/>")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: ambient.d.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"declare"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"module"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'*.mdx'"),s("span",{style:{color:"#ADBAC7"}}," {")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},"any")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"declare"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"module"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"react"')]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: MultiFileDocs.mdx")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"## "),s("span",{style:{color:"#F69D50"}},"Hello"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"world")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @filename: index.tsx")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," React "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"react"')]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," MultiFileDocs "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"./MultiFileDocs.mdx"')]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#F69D50"}}," ")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: ambient.d.ts")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"declare"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"module"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'*.mdx'"),s("span",{style:{color:"#24292E"}}," {")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," any")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"declare"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"module"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"react"')]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: MultiFileDocs.mdx")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"## "),s("span",{style:{color:"#6F42C1"}},"Hello"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"world")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @filename: index.tsx")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," React "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"react"')]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," MultiFileDocs "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},'"./MultiFileDocs.mdx"')]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," <"),s("span",{style:{color:"#6F42C1"}},"MultiFileDocs"),s("span",{style:{color:"#24292E"}},"/>")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br"),s("span",{class:"line-number"},"15"),s("br"),s("span",{class:"line-number"},"16"),s("br"),s("span",{class:"line-number"},"17"),s("br")])])])],-1);function g(A,D,f,F,C,k){const e=a;return o(),t("div",null,[r,i(e,{readTime:"2",words:"477"}),d,y,m,u,b,v,h])}const _=n(c,[["render",g]]);export{B as __pageData,_ as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.aea0802f.js b/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.aea0802f.js deleted file mode 100644 index 665f11ab..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.aea0802f.js +++ /dev/null @@ -1,71 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as t,H as i,k as s,a as l,Q as p}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse(`{"title":"Multi-file","description":"Twoslash code examples aren't limited to creating a single file. You can write any file to the virtual file system used by TypeScript to power your code examples.","frontmatter":{"description":"Twoslash code examples aren't limited to creating a single file. You can write any file to the virtual file system used by TypeScript to power your code examples.","title":"Multi-file"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/multi-file.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/multi-file.md","lastUpdated":1695377563000}`),c={name:"application/vitepress-plugin-shiki-twoslash/api/multi-file.md"},r=s("h1",{id:"multi-file",tabindex:"-1"},[l("Multi-file "),s("a",{class:"header-anchor",href:"#multi-file","aria-label":'Permalink to "Multi-file"'},"​")],-1),d=p('

    Twoslash code examples aren't limited to creating a single file, by using // @filename: [file] you can write any file to the virtual file system used by TypeScript to power your code examples.

    @filename: [file]

    Most of the time, you don't need to think about the underlaying virtual file system in a code example, but when you have imports between them it becomes important to know. Twoslash will default to creating an index.[type] based on the langauge passed to the code example:

    ts
    ts
    // I'm index.ts
    ts
    // I'm index.ts
    md
    ```ts twoslash\n// I'm index.ts\n```
    ```ts twoslash\n// I'm index.ts\n```
    tsx
    tsx
    // I'm index.tsx
    tsx
    // I'm index.tsx
    md
    ```tsx twoslash\n// I'm index.tsx\n```
    ```tsx twoslash\n// I'm index.tsx\n```
    js
    js
    // I'm index.tjs
    js
    // I'm index.tjs
    md
    ```js twoslash\n// I'm index.tjs\n```
    ```js twoslash\n// I'm index.tjs\n```

    Then until Twoslash hits another // @filename: [file], the parser keeps adding new lines into the same file. After seeing @filename Twoslash creates a new virtual file-system file and adds the new lines to that. You can't edit a file after it was created, but you can overwrite it.

    It can be any file. For example, if you want to quickly fake a node module:

    ',8),y=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-vtxAX",id:"tab-sC5pHjF",checked:"checked"}),s("label",{for:"tab-sC5pHjF"},"output"),s("input",{type:"radio",name:"group-vtxAX",id:"tab-ZOZjfQI"}),s("label",{for:"tab-ZOZjfQI"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function doit(): string"},"doit")]),s("span",{style:{color:"#839496"}},"()"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function doit(): string -import doit`},"doit")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'mylib'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function doit(): string -import doit`},"doit")]),s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function doit(): string"},"doit")]),s("span",{style:{color:"#657B83"}},"()"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function doit(): string -import doit`},"doit")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'mylib'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function doit(): string -import doit`},"doit")]),s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("p",null,"This code example sets up the types for a non-existent npm module, and TypeScript picks it up as the definitions in the same way it would in a non-virtual TypeScript project."),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#839496"}},"()"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: index.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'mylib'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#657B83"}},"()"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: index.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'mylib'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br")])])])],-1),m=s("p",null,"You can also set up a JSON object which can be imported in a TypeScript file:",-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-IWu7r",id:"tab-HpHNm4q",checked:"checked"}),s("label",{for:"tab-HpHNm4q"},"output"),s("input",{type:"radio",name:"group-IWu7r",id:"tab-22o7pAK"}),s("label",{for:"tab-22o7pAK"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// @filename: app.json")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"{ "),s("span",{style:{color:"#2AA198"}},'"version"'),s("span",{style:{color:"#839496"}},": "),s("span",{style:{color:"#2AA198"}},'"23.2.3"'),s("span",{style:{color:"#839496"}}," }")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"./app.json"')]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'(property) "version": string',style:{"border-bottom":"solid 2px lightgrey"}},"version")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l('(property) "version": string')])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// @filename: app.json")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"{ "),s("span",{style:{color:"#2AA198"}},'"version"'),s("span",{style:{color:"#657B83"}},": "),s("span",{style:{color:"#2AA198"}},'"23.2.3"'),s("span",{style:{color:"#657B83"}}," }")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"./app.json"')]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'(property) "version": string',style:{"border-bottom":"solid 2px lightgrey"}},"version")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l('(property) "version": string')])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @resolveJsonModule")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: app.json")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"{ "),s("span",{style:{color:"#2AA198"}},'"version"'),s("span",{style:{color:"#839496"}},": "),s("span",{style:{color:"#2AA198"}},'"23.2.3"'),s("span",{style:{color:"#839496"}}," }")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: index.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"appSettings"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"./app.json"')]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"appSettings"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"version")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @resolveJsonModule")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: app.json")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"{ "),s("span",{style:{color:"#2AA198"}},'"version"'),s("span",{style:{color:"#657B83"}},": "),s("span",{style:{color:"#2AA198"}},'"23.2.3"'),s("span",{style:{color:"#657B83"}}," }")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: index.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"appSettings"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"./app.json"')]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"appSettings"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"version")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br")])])])],-1),b=s("p",null,[l("Finally, the following code allows importing non-TypeScript content. There is a "),s("code",null,".d.ts"),l(` file which globally says 'md files are OK to import' and 'the module "react" exists, but don't worry about the details'.`)],-1),v=s("p",null,[l("Then for a user, they only see the imports and exports inside "),s("code",null,"index.tsx"),l(".")],-1),h=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-A33Oa",id:"tab-3tnn78l",checked:"checked"}),s("label",{for:"tab-3tnn78l"},"output"),s("input",{type:"radio",name:"group-A33Oa",id:"tab-bEBCxLZ"}),s("label",{for:"tab-bEBCxLZ"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) module "react" -import React`},"React")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"./MultiFileDocs.mdx"')]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," () "),s("span",{style:{color:"#93A1A1"}},"=>"),s("span",{style:{color:"#839496"}}," <"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#839496"}},"/>")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) module "react" -import React`},"React")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"./MultiFileDocs.mdx"')]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," () "),s("span",{style:{color:"#586E75"}},"=>"),s("span",{style:{color:"#657B83"}}," <"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#657B83"}},"/>")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: ambient.d.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"declare"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"module"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'*.mdx'"),s("span",{style:{color:"#839496"}}," {")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"any")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"declare"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"module"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: MultiFileDocs.mdx")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"## "),s("span",{style:{color:"#CB4B16"}},"Hello"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},"world")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: index.tsx")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"React"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"MultiFileDocs"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"./MultiFileDocs.mdx"')]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," () "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"=>"),s("span",{style:{color:"#839496"}}," <"),s("span",{style:{color:"#CB4B16"}},"MultiFileDocs"),s("span",{style:{color:"#839496"}},"/>")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: ambient.d.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"declare"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"module"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'*.mdx'"),s("span",{style:{color:"#657B83"}}," {")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"any")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"declare"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"module"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: MultiFileDocs.mdx")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"## "),s("span",{style:{color:"#CB4B16"}},"Hello"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},"world")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: index.tsx")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"React"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"MultiFileDocs"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"./MultiFileDocs.mdx"')]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," () "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"=>"),s("span",{style:{color:"#657B83"}}," <"),s("span",{style:{color:"#CB4B16"}},"MultiFileDocs"),s("span",{style:{color:"#657B83"}},"/>")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br"),s("span",{class:"line-number"},"15"),s("br"),s("span",{class:"line-number"},"16"),s("br"),s("span",{class:"line-number"},"17"),s("br")])])])],-1);function g(f,B,A,k,w,x){const e=a;return n(),t("div",null,[r,i(e,{readTime:"2",words:"477"}),d,y,m,u,b,v,h])}const F=o(c,[["render",g]]);export{E as __pageData,F as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.aea0802f.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.aea0802f.lean.js deleted file mode 100644 index 28039734..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_multi-file.md.aea0802f.lean.js +++ /dev/null @@ -1,71 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as t,H as i,k as s,a as l,Q as p}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse(`{"title":"Multi-file","description":"Twoslash code examples aren't limited to creating a single file. You can write any file to the virtual file system used by TypeScript to power your code examples.","frontmatter":{"description":"Twoslash code examples aren't limited to creating a single file. You can write any file to the virtual file system used by TypeScript to power your code examples.","title":"Multi-file"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/multi-file.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/multi-file.md","lastUpdated":1695377563000}`),c={name:"application/vitepress-plugin-shiki-twoslash/api/multi-file.md"},r=s("h1",{id:"multi-file",tabindex:"-1"},[l("Multi-file "),s("a",{class:"header-anchor",href:"#multi-file","aria-label":'Permalink to "Multi-file"'},"​")],-1),d=p("",8),y=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-vtxAX",id:"tab-sC5pHjF",checked:"checked"}),s("label",{for:"tab-sC5pHjF"},"output"),s("input",{type:"radio",name:"group-vtxAX",id:"tab-ZOZjfQI"}),s("label",{for:"tab-ZOZjfQI"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function doit(): string"},"doit")]),s("span",{style:{color:"#839496"}},"()"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function doit(): string -import doit`},"doit")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'mylib'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function doit(): string -import doit`},"doit")]),s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function doit(): string"},"doit")]),s("span",{style:{color:"#657B83"}},"()"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function doit(): string -import doit`},"doit")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'mylib'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function doit(): string -import doit`},"doit")]),s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("p",null,"This code example sets up the types for a non-existent npm module, and TypeScript picks it up as the definitions in the same way it would in a non-virtual TypeScript project."),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#839496"}},"()"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: index.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'mylib'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: node_modules/@types/mylib/index.d.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#657B83"}},"()"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: index.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'mylib'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"log"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},"doit"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br")])])])],-1),m=s("p",null,"You can also set up a JSON object which can be imported in a TypeScript file:",-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-IWu7r",id:"tab-HpHNm4q",checked:"checked"}),s("label",{for:"tab-HpHNm4q"},"output"),s("input",{type:"radio",name:"group-IWu7r",id:"tab-22o7pAK"}),s("label",{for:"tab-22o7pAK"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// @filename: app.json")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"{ "),s("span",{style:{color:"#2AA198"}},'"version"'),s("span",{style:{color:"#839496"}},": "),s("span",{style:{color:"#2AA198"}},'"23.2.3"'),s("span",{style:{color:"#839496"}}," }")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"./app.json"')]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'(property) "version": string',style:{"border-bottom":"solid 2px lightgrey"}},"version")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l('(property) "version": string')])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// @filename: app.json")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"{ "),s("span",{style:{color:"#2AA198"}},'"version"'),s("span",{style:{color:"#657B83"}},": "),s("span",{style:{color:"#2AA198"}},'"23.2.3"'),s("span",{style:{color:"#657B83"}}," }")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// @filename: index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"./app.json"')]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import appSettings"},"appSettings")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'(property) "version": string',style:{"border-bottom":"solid 2px lightgrey"}},"version")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l('(property) "version": string')])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @resolveJsonModule")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: app.json")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"{ "),s("span",{style:{color:"#2AA198"}},'"version"'),s("span",{style:{color:"#839496"}},": "),s("span",{style:{color:"#2AA198"}},'"23.2.3"'),s("span",{style:{color:"#839496"}}," }")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: index.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"appSettings"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"./app.json"')]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"appSettings"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"version")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @resolveJsonModule")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: app.json")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"{ "),s("span",{style:{color:"#2AA198"}},'"version"'),s("span",{style:{color:"#657B83"}},": "),s("span",{style:{color:"#2AA198"}},'"23.2.3"'),s("span",{style:{color:"#657B83"}}," }")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: index.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"appSettings"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"./app.json"')]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"appSettings"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"version")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br")])])])],-1),b=s("p",null,[l("Finally, the following code allows importing non-TypeScript content. There is a "),s("code",null,".d.ts"),l(` file which globally says 'md files are OK to import' and 'the module "react" exists, but don't worry about the details'.`)],-1),v=s("p",null,[l("Then for a user, they only see the imports and exports inside "),s("code",null,"index.tsx"),l(".")],-1),h=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-A33Oa",id:"tab-3tnn78l",checked:"checked"}),s("label",{for:"tab-3tnn78l"},"output"),s("input",{type:"radio",name:"group-A33Oa",id:"tab-bEBCxLZ"}),s("label",{for:"tab-bEBCxLZ"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) module "react" -import React`},"React")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"./MultiFileDocs.mdx"')]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," () "),s("span",{style:{color:"#93A1A1"}},"=>"),s("span",{style:{color:"#839496"}}," <"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#839496"}},"/>")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) module "react" -import React`},"React")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"./MultiFileDocs.mdx"')]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," () "),s("span",{style:{color:"#586E75"}},"=>"),s("span",{style:{color:"#657B83"}}," <"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"import MultiFileDocs"},"MultiFileDocs")]),s("span",{style:{color:"#657B83"}},"/>")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: ambient.d.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"declare"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"module"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'*.mdx'"),s("span",{style:{color:"#839496"}}," {")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"any")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"declare"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"module"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: MultiFileDocs.mdx")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"## "),s("span",{style:{color:"#CB4B16"}},"Hello"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},"world")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @filename: index.tsx")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"React"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"MultiFileDocs"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},'"./MultiFileDocs.mdx"')]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," () "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"=>"),s("span",{style:{color:"#839496"}}," <"),s("span",{style:{color:"#CB4B16"}},"MultiFileDocs"),s("span",{style:{color:"#839496"}},"/>")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: ambient.d.ts")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"declare"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"module"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'*.mdx'"),s("span",{style:{color:"#657B83"}}," {")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"any")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"declare"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"module"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: MultiFileDocs.mdx")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"## "),s("span",{style:{color:"#CB4B16"}},"Hello"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},"world")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @filename: index.tsx")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"React"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"react"')]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"MultiFileDocs"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},'"./MultiFileDocs.mdx"')]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," () "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"=>"),s("span",{style:{color:"#657B83"}}," <"),s("span",{style:{color:"#CB4B16"}},"MultiFileDocs"),s("span",{style:{color:"#657B83"}},"/>")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br"),s("span",{class:"line-number"},"10"),s("br"),s("span",{class:"line-number"},"11"),s("br"),s("span",{class:"line-number"},"12"),s("br"),s("span",{class:"line-number"},"13"),s("br"),s("span",{class:"line-number"},"14"),s("br"),s("span",{class:"line-number"},"15"),s("br"),s("span",{class:"line-number"},"16"),s("br"),s("span",{class:"line-number"},"17"),s("br")])])])],-1);function g(f,B,A,k,w,x){const e=a;return n(),t("div",null,[r,i(e,{readTime:"2",words:"477"}),d,y,m,u,b,v,h])}const F=o(c,[["render",g]]);export{E as __pageData,F as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.8c3dbc97.js b/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.8c3dbc97.js new file mode 100644 index 00000000..1bd4818d --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.8c3dbc97.js @@ -0,0 +1,17 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as c,k as s,a as l,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const B=JSON.parse('{"title":"Queries","description":"One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code.","frontmatter":{"description":"One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code.","title":"Queries"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/queries.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/queries.md","lastUpdated":1699051935000}'),i={name:"application/vitepress-plugin-shiki-twoslash/api/queries.md"},p=s("h1",{id:"queries",tabindex:"-1"},[l("Queries "),s("a",{class:"header-anchor",href:"#queries","aria-label":'Permalink to "Queries"'},"​")],-1),d=r('

    One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code. Twoslash comes with two different ways to query your code: ?^ and ?|.

    Extract Type ^?

    Using ^? you can pull out type information about a particular identifier in the line of code above it.

    ',3),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-Mtb6R",id:"tab-CWdV32g",checked:"checked"}),s("label",{for:"tab-CWdV32g"},"output"),s("input",{type:"radio",name:"group-Mtb6R",id:"tab-dbqcKEQ"}),s("label",{for:"tab-dbqcKEQ"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'Hello'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const msg: string",style:{"border-bottom":"solid 2px lightgrey"}},"msg")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:'const hi: "Hello"'},"hi"),l()]),s("span",{style:{color:"#F47067"}},"+"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"', world'")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const msg: string")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'Hello'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const msg: string",style:{"border-bottom":"solid 2px lightgrey"}},"msg")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:'const hi: "Hello"'},"hi"),l()]),s("span",{style:{color:"#D73A49"}},"+"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"', world'")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const msg: string")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"hi"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'Hello'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"msg"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," hi "),s("span",{style:{color:"#F47067"}},"+"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"', world'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"hi"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'Hello'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"msg"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," hi "),s("span",{style:{color:"#D73A49"}},"+"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"', world'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),y=s("h2",{id:"completions",tabindex:"-1"},[l("Completions "),s("code",null,"^|"),l(),s("a",{class:"header-anchor",href:"#completions","aria-label":'Permalink to "Completions `^|`"'},"​")],-1),h=s("p",null,[l("Using "),s("code",null,"^|"),l(" you can pull out information about a what the auto-complete looks like at a particular location.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-C6nYW",id:"tab-DtdCr4T",checked:"checked"}),s("label",{for:"tab-DtdCr4T"},"output"),s("input",{type:"radio",name:"group-C6nYW",id:"tab-XTB-sHQ"}),s("label",{for:"tab-XTB-sHQ"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l("."),s("data-lsp",{lsp:"any"},"e")])]),s("div",{class:"meta-line"},[l("         "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"e"),l("rror")])])])])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l("."),s("data-lsp",{lsp:"any"},"e")])]),s("div",{class:"meta-line"},[l("         "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"e"),l("rror")])])])])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @noErrors")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"console.e")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ^|")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @noErrors")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"console.e")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ^|")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),b=s("div",{class:"info custom-block"},[s("p",{class:"custom-block-title"},"INFO"),s("p",null,[l("Note that the compiler flag for "),s("a",{href:"./errors#noerrors"},[s("code",null,"// @noErrors")]),l(" is set, because "),s("code",null,"console.e"),l(" is a failing TypeScript code sample but we don't really care about that.")])],-1);function g(v,A,C,f,k,_){const e=o;return n(),t("div",null,[p,c(e,{readTime:"1",words:"167"}),d,u,y,h,m,b])}const E=a(i,[["render",g]]);export{B as __pageData,E as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.8c3dbc97.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.8c3dbc97.lean.js new file mode 100644 index 00000000..13dc120c --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.8c3dbc97.lean.js @@ -0,0 +1,17 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as c,k as s,a as l,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const B=JSON.parse('{"title":"Queries","description":"One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code.","frontmatter":{"description":"One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code.","title":"Queries"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/queries.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/queries.md","lastUpdated":1699051935000}'),i={name:"application/vitepress-plugin-shiki-twoslash/api/queries.md"},p=s("h1",{id:"queries",tabindex:"-1"},[l("Queries "),s("a",{class:"header-anchor",href:"#queries","aria-label":'Permalink to "Queries"'},"​")],-1),d=r("",3),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-Mtb6R",id:"tab-CWdV32g",checked:"checked"}),s("label",{for:"tab-CWdV32g"},"output"),s("input",{type:"radio",name:"group-Mtb6R",id:"tab-dbqcKEQ"}),s("label",{for:"tab-dbqcKEQ"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'Hello'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const msg: string",style:{"border-bottom":"solid 2px lightgrey"}},"msg")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:'const hi: "Hello"'},"hi"),l()]),s("span",{style:{color:"#F47067"}},"+"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"', world'")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const msg: string")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'Hello'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const msg: string",style:{"border-bottom":"solid 2px lightgrey"}},"msg")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:'const hi: "Hello"'},"hi"),l()]),s("span",{style:{color:"#D73A49"}},"+"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"', world'")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const msg: string")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"hi"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'Hello'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"msg"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," hi "),s("span",{style:{color:"#F47067"}},"+"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"', world'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"hi"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'Hello'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"msg"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," hi "),s("span",{style:{color:"#D73A49"}},"+"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"', world'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),y=s("h2",{id:"completions",tabindex:"-1"},[l("Completions "),s("code",null,"^|"),l(),s("a",{class:"header-anchor",href:"#completions","aria-label":'Permalink to "Completions `^|`"'},"​")],-1),h=s("p",null,[l("Using "),s("code",null,"^|"),l(" you can pull out information about a what the auto-complete looks like at a particular location.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-C6nYW",id:"tab-DtdCr4T",checked:"checked"}),s("label",{for:"tab-DtdCr4T"},"output"),s("input",{type:"radio",name:"group-C6nYW",id:"tab-XTB-sHQ"}),s("label",{for:"tab-XTB-sHQ"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l("."),s("data-lsp",{lsp:"any"},"e")])]),s("div",{class:"meta-line"},[l("         "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"e"),l("rror")])])])])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"var console: Console"},"console"),l("."),s("data-lsp",{lsp:"any"},"e")])]),s("div",{class:"meta-line"},[l("         "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"e"),l("rror")])])])])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// @noErrors")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"console.e")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ^|")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// @noErrors")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"console.e")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ^|")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),b=s("div",{class:"info custom-block"},[s("p",{class:"custom-block-title"},"INFO"),s("p",null,[l("Note that the compiler flag for "),s("a",{href:"./errors#noerrors"},[s("code",null,"// @noErrors")]),l(" is set, because "),s("code",null,"console.e"),l(" is a failing TypeScript code sample but we don't really care about that.")])],-1);function g(v,A,C,f,k,_){const e=o;return n(),t("div",null,[p,c(e,{readTime:"1",words:"167"}),d,u,y,h,m,b])}const E=a(i,[["render",g]]);export{B as __pageData,E as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.9bd11a96.js b/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.9bd11a96.js deleted file mode 100644 index 432a7271..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.9bd11a96.js +++ /dev/null @@ -1,17 +0,0 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as t,c as n,H as c,k as s,a as l,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"Queries","description":"One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code.","frontmatter":{"description":"One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code.","title":"Queries"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/queries.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/queries.md","lastUpdated":1695377563000}'),i={name:"application/vitepress-plugin-shiki-twoslash/api/queries.md"},p=s("h1",{id:"queries",tabindex:"-1"},[l("Queries "),s("a",{class:"header-anchor",href:"#queries","aria-label":'Permalink to "Queries"'},"​")],-1),d=r('

    One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code. Twoslash comes with two different ways to query your code: ?^ and ?|.

    Extract Type ^?

    Using ^? you can pull out type information about a particular identifier in the line of code above it.

    ',3),y=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-_2Nlk",id:"tab-HbIaKgk",checked:"checked"}),s("label",{for:"tab-HbIaKgk"},"output"),s("input",{type:"radio",name:"group-_2Nlk",id:"tab-I0Luw3K"}),s("label",{for:"tab-I0Luw3K"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'Hello'")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const msg: string",style:{"border-bottom":"solid 2px lightgrey"}},"msg")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"+"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"', world'")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const msg: string")])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'Hello'")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const msg: string",style:{"border-bottom":"solid 2px lightgrey"}},"msg")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"+"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"', world'")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const msg: string")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"hi"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'Hello'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"msg"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"hi"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"+"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"', world'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"hi"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'Hello'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"msg"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"hi"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"+"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"', world'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),u=s("h2",{id:"completions",tabindex:"-1"},[l("Completions "),s("code",null,"^|"),l(),s("a",{class:"header-anchor",href:"#completions","aria-label":'Permalink to "Completions `^|`"'},"​")],-1),h=s("p",null,[l("Using "),s("code",null,"^|"),l(" you can pull out information about a what the auto-complete looks like at a particular location.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-9O7eN",id:"tab-CL2gyud",checked:"checked"}),s("label",{for:"tab-CL2gyud"},"output"),s("input",{type:"radio",name:"group-9O7eN",id:"tab-6a-JRPE"}),s("label",{for:"tab-6a-JRPE"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"e")])]),s("div",{class:"meta-line"},[l("         "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"e"),l("rror")])])])])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"e")])]),s("div",{class:"meta-line"},[l("         "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"e"),l("rror")])])])])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @noErrors")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"e")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^|")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @noErrors")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"e")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^|")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),b=s("div",{class:"info custom-block"},[s("p",{class:"custom-block-title"},"INFO"),s("p",null,[l("Note that the compiler flag for "),s("a",{href:"./errors#noerrors"},[s("code",null,"// @noErrors")]),l(" is set, because "),s("code",null,"console.e"),l(" is a failing TypeScript code sample but we don't really care about that.")])],-1);function g(v,f,B,k,_,w){const o=e;return t(),n("div",null,[p,c(o,{readTime:"1",words:"167"}),d,y,u,h,m,b])}const C=a(i,[["render",g]]);export{T as __pageData,C as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.9bd11a96.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.9bd11a96.lean.js deleted file mode 100644 index 6065e5a6..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_queries.md.9bd11a96.lean.js +++ /dev/null @@ -1,17 +0,0 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as t,c as n,H as c,k as s,a as l,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"Queries","description":"One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code.","frontmatter":{"description":"One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code.","title":"Queries"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/queries.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/queries.md","lastUpdated":1695377563000}'),i={name:"application/vitepress-plugin-shiki-twoslash/api/queries.md"},p=s("h1",{id:"queries",tabindex:"-1"},[l("Queries "),s("a",{class:"header-anchor",href:"#queries","aria-label":'Permalink to "Queries"'},"​")],-1),d=r("",3),y=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-_2Nlk",id:"tab-HbIaKgk",checked:"checked"}),s("label",{for:"tab-HbIaKgk"},"output"),s("input",{type:"radio",name:"group-_2Nlk",id:"tab-I0Luw3K"}),s("label",{for:"tab-I0Luw3K"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'Hello'")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const msg: string",style:{"border-bottom":"solid 2px lightgrey"}},"msg")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"+"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"', world'")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const msg: string")])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'Hello'")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const msg: string",style:{"border-bottom":"solid 2px lightgrey"}},"msg")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const hi: "Hello"'},"hi")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"+"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"', world'")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const msg: string")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"hi"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'Hello'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"msg"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"hi"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"+"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"', world'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"hi"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'Hello'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"msg"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"hi"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"+"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"', world'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),u=s("h2",{id:"completions",tabindex:"-1"},[l("Completions "),s("code",null,"^|"),l(),s("a",{class:"header-anchor",href:"#completions","aria-label":'Permalink to "Completions `^|`"'},"​")],-1),h=s("p",null,[l("Using "),s("code",null,"^|"),l(" you can pull out information about a what the auto-complete looks like at a particular location.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-9O7eN",id:"tab-CL2gyud",checked:"checked"}),s("label",{for:"tab-CL2gyud"},"output"),s("input",{type:"radio",name:"group-9O7eN",id:"tab-6a-JRPE"}),s("label",{for:"tab-6a-JRPE"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"e")])]),s("div",{class:"meta-line"},[l("         "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"e"),l("rror")])])])])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"e")])]),s("div",{class:"meta-line"},[l("         "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"e"),l("rror")])])])])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// @noErrors")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},"e")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^|")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// @noErrors")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"console"),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},"e")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^|")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br")])])])],-1),b=s("div",{class:"info custom-block"},[s("p",{class:"custom-block-title"},"INFO"),s("p",null,[l("Note that the compiler flag for "),s("a",{href:"./errors#noerrors"},[s("code",null,"// @noErrors")]),l(" is set, because "),s("code",null,"console.e"),l(" is a failing TypeScript code sample but we don't really care about that.")])],-1);function g(v,f,B,k,_,w){const o=e;return t(),n("div",null,[p,c(o,{readTime:"1",words:"167"}),d,y,u,h,m,b])}const C=a(i,[["render",g]]);export{T as __pageData,C as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.9dbcbe1c.js b/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.9dbcbe1c.js deleted file mode 100644 index 1b7d0c3e..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.9dbcbe1c.js +++ /dev/null @@ -1,45 +0,0 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as c,k as s,a as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"@types","description":"Using external libraries with Twoslash code examples.","frontmatter":{"description":"Using external libraries with Twoslash code examples.","title":"@types"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/types.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/types.md","lastUpdated":1695377563000}'),i={name:"application/vitepress-plugin-shiki-twoslash/api/types.md"},r=s("h1",{id:"types",tabindex:"-1"},[l("@types "),s("a",{class:"header-anchor",href:"#types","aria-label":'Permalink to "@types"'},"​")],-1),p=s("p",null,"For most examples, you probably need to import external libraries into your code examples.",-1),y=s("p",null,[l("Twoslash works by faking a virtual file system over your existing file system. This means any "),s("code",null,"@types"),l(" or libraries with TypeScript definitions should work out of the box with no config.")],-1),d=s("h2",{id:"local-sources",tabindex:"-1"},[l("Local Sources "),s("a",{class:"header-anchor",href:"#local-sources","aria-label":'Permalink to "Local Sources"'},"​")],-1),f=s("p",null,"Simply import locally installed libraries and Twoslash can pick up types:",-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-7pu-P",id:"tab-gi03a3y",checked:"checked"}),s("label",{for:"tab-gi03a3y"},"output"),s("input",{type:"radio",name:"group-7pu-P",id:"tab-uiBOtRN"}),s("label",{for:"tab-uiBOtRN"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const config: UserConfig",style:{"border-bottom":"solid 2px lightgrey"}},"config")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({})")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const config: UserConfig")])]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const config: UserConfig"},"config")])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const config: UserConfig",style:{"border-bottom":"solid 2px lightgrey"}},"config")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({})")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const config: UserConfig")])]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const config: UserConfig"},"config")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},"defineConfig"),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"config"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"defineConfig"),s("span",{style:{color:"#839496"}},"({})")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"config")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},"defineConfig"),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"config"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"defineConfig"),s("span",{style:{color:"#657B83"}},"({})")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"config")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br")])])])],-1),g=s("h2",{id:"globals",tabindex:"-1"},[l("Globals "),s("a",{class:"header-anchor",href:"#globals","aria-label":'Permalink to "Globals"'},"​")],-1),m=s("p",null,[l("Setting up globals is a little bit more complex, but not drastically. You need to use the "),s("a",{href:"https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-",target:"_blank",rel:"noreferrer"},"triple slash reference"),l(" which adds a particular library to the global scope.")],-1),h=s("p",null,"For example, setting up Node imports and globals etc.",-1),b=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-nQ8lx",id:"tab-Oeqww3A",checked:"checked"}),s("label",{for:"tab-Oeqww3A"},"output"),s("input",{type:"radio",name:"group-nQ8lx",id:"tab-bJReA55"}),s("label",{for:"tab-bJReA55"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void -import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'fs'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions | undefined): void -import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'myfile.txt'"),s("span",{style:{color:"#839496"}},", "),s("span",{style:{color:"#2AA198"}},"'// TODO'"),s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void -import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'fs'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions | undefined): void -import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'myfile.txt'"),s("span",{style:{color:"#657B83"}},", "),s("span",{style:{color:"#2AA198"}},"'// TODO'"),s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"/// <"),s("span",{style:{color:"#268BD2","font-style":"italic"}},"reference"),s("span",{style:{color:"#586E75","font-style":"italic"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"types"),s("span",{style:{color:"#859900","font-style":"italic"}},"="),s("span",{style:{color:"#2AA198","font-style":"italic"}},'"node"'),s("span",{style:{color:"#586E75","font-style":"italic"}}," />")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},"writeFileSync"),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'fs'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"writeFileSync"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'myfile.txt'"),s("span",{style:{color:"#839496"}},", "),s("span",{style:{color:"#2AA198"}},"'// TODO'"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"/// <"),s("span",{style:{color:"#268BD2","font-style":"italic"}},"reference"),s("span",{style:{color:"#93A1A1","font-style":"italic"}}," types"),s("span",{style:{color:"#859900","font-style":"italic"}},"="),s("span",{style:{color:"#2AA198","font-style":"italic"}},'"node"'),s("span",{style:{color:"#93A1A1","font-style":"italic"}}," />")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},"writeFileSync"),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'fs'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"writeFileSync"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'myfile.txt'"),s("span",{style:{color:"#657B83"}},", "),s("span",{style:{color:"#2AA198"}},"'// TODO'"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br")])])])],-1),v=s("p",null,[l("APIs like "),s("a",{href:"https://vitest.dev",target:"_blank",rel:"noreferrer"},"Vitest"),l(" are similar cases where you would use a triple slash reference.")],-1),B=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-Yx1mx",id:"tab-XuNO3fX",checked:"checked"}),s("label",{for:"tab-XuNO3fX"},"output"),s("input",{type:"radio",name:"group-Yx1mx",id:"tab-V645NLg"}),s("label",{for:"tab-V645NLg"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const test: any"},"test")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'my tests'"),s("span",{style:{color:"#839496"}},", () "),s("span",{style:{color:"#93A1A1"}},"=>"),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const expect: ExpectStatic",style:{"border-bottom":"solid 2px lightgrey"}},"expect")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#839496"}},")."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"toEqual")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#839496"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const expect: ExpectStatic")])]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"})")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const test: any"},"test")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'my tests'"),s("span",{style:{color:"#657B83"}},", () "),s("span",{style:{color:"#586E75"}},"=>"),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const expect: ExpectStatic",style:{"border-bottom":"solid 2px lightgrey"}},"expect")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#657B83"}},")."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"toEqual")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#657B83"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const expect: ExpectStatic")])]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"/// <"),s("span",{style:{color:"#268BD2","font-style":"italic"}},"reference"),s("span",{style:{color:"#586E75","font-style":"italic"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"types"),s("span",{style:{color:"#859900","font-style":"italic"}},"="),s("span",{style:{color:"#2AA198","font-style":"italic"}},'"vitest/globals"'),s("span",{style:{color:"#586E75","font-style":"italic"}}," />")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"test"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'my tests'"),s("span",{style:{color:"#839496"}},", () "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"=>"),s("span",{style:{color:"#839496"}}," {")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"expect"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#839496"}},")."),s("span",{style:{color:"#268BD2"}},"toEqual"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"})")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"/// <"),s("span",{style:{color:"#268BD2","font-style":"italic"}},"reference"),s("span",{style:{color:"#93A1A1","font-style":"italic"}}," types"),s("span",{style:{color:"#859900","font-style":"italic"}},"="),s("span",{style:{color:"#2AA198","font-style":"italic"}},'"vitest/globals"'),s("span",{style:{color:"#93A1A1","font-style":"italic"}}," />")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"test"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'my tests'"),s("span",{style:{color:"#657B83"}},", () "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"=>"),s("span",{style:{color:"#657B83"}}," {")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"expect"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#657B83"}},")."),s("span",{style:{color:"#268BD2"}},"toEqual"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"})")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1);function A(w,D,k,C,x,_){const e=o;return n(),t("div",null,[r,c(e,{readTime:"1",words:"230"}),p,y,d,f,u,g,m,h,b,v,B])}const O=a(i,[["render",A]]);export{T as __pageData,O as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.9dbcbe1c.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.9dbcbe1c.lean.js deleted file mode 100644 index 1b7d0c3e..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.9dbcbe1c.lean.js +++ /dev/null @@ -1,45 +0,0 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as c,k as s,a as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"@types","description":"Using external libraries with Twoslash code examples.","frontmatter":{"description":"Using external libraries with Twoslash code examples.","title":"@types"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/types.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/types.md","lastUpdated":1695377563000}'),i={name:"application/vitepress-plugin-shiki-twoslash/api/types.md"},r=s("h1",{id:"types",tabindex:"-1"},[l("@types "),s("a",{class:"header-anchor",href:"#types","aria-label":'Permalink to "@types"'},"​")],-1),p=s("p",null,"For most examples, you probably need to import external libraries into your code examples.",-1),y=s("p",null,[l("Twoslash works by faking a virtual file system over your existing file system. This means any "),s("code",null,"@types"),l(" or libraries with TypeScript definitions should work out of the box with no config.")],-1),d=s("h2",{id:"local-sources",tabindex:"-1"},[l("Local Sources "),s("a",{class:"header-anchor",href:"#local-sources","aria-label":'Permalink to "Local Sources"'},"​")],-1),f=s("p",null,"Simply import locally installed libraries and Twoslash can pick up types:",-1),u=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-7pu-P",id:"tab-gi03a3y",checked:"checked"}),s("label",{for:"tab-gi03a3y"},"output"),s("input",{type:"radio",name:"group-7pu-P",id:"tab-uiBOtRN"}),s("label",{for:"tab-uiBOtRN"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const config: UserConfig",style:{"border-bottom":"solid 2px lightgrey"}},"config")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({})")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const config: UserConfig")])]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const config: UserConfig"},"config")])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const config: UserConfig",style:{"border-bottom":"solid 2px lightgrey"}},"config")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({})")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const config: UserConfig")])]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const config: UserConfig"},"config")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},"defineConfig"),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"config"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"defineConfig"),s("span",{style:{color:"#839496"}},"({})")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"config")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},"defineConfig"),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-weight":"bold"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"config"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"defineConfig"),s("span",{style:{color:"#657B83"}},"({})")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"config")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br")])])])],-1),g=s("h2",{id:"globals",tabindex:"-1"},[l("Globals "),s("a",{class:"header-anchor",href:"#globals","aria-label":'Permalink to "Globals"'},"​")],-1),m=s("p",null,[l("Setting up globals is a little bit more complex, but not drastically. You need to use the "),s("a",{href:"https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-",target:"_blank",rel:"noreferrer"},"triple slash reference"),l(" which adds a particular library to the global scope.")],-1),h=s("p",null,"For example, setting up Node imports and globals etc.",-1),b=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-nQ8lx",id:"tab-Oeqww3A",checked:"checked"}),s("label",{for:"tab-Oeqww3A"},"output"),s("input",{type:"radio",name:"group-nQ8lx",id:"tab-bJReA55"}),s("label",{for:"tab-bJReA55"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void -import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'fs'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions | undefined): void -import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'myfile.txt'"),s("span",{style:{color:"#839496"}},", "),s("span",{style:{color:"#2AA198"}},"'// TODO'"),s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void -import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'fs'")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions | undefined): void -import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'myfile.txt'"),s("span",{style:{color:"#657B83"}},", "),s("span",{style:{color:"#2AA198"}},"'// TODO'"),s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"/// <"),s("span",{style:{color:"#268BD2","font-style":"italic"}},"reference"),s("span",{style:{color:"#586E75","font-style":"italic"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"types"),s("span",{style:{color:"#859900","font-style":"italic"}},"="),s("span",{style:{color:"#2AA198","font-style":"italic"}},'"node"'),s("span",{style:{color:"#586E75","font-style":"italic"}}," />")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},"writeFileSync"),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'fs'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"writeFileSync"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'myfile.txt'"),s("span",{style:{color:"#839496"}},", "),s("span",{style:{color:"#2AA198"}},"'// TODO'"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"/// <"),s("span",{style:{color:"#268BD2","font-style":"italic"}},"reference"),s("span",{style:{color:"#93A1A1","font-style":"italic"}}," types"),s("span",{style:{color:"#859900","font-style":"italic"}},"="),s("span",{style:{color:"#2AA198","font-style":"italic"}},'"node"'),s("span",{style:{color:"#93A1A1","font-style":"italic"}}," />")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},"writeFileSync"),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'fs'")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"writeFileSync"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'myfile.txt'"),s("span",{style:{color:"#657B83"}},", "),s("span",{style:{color:"#2AA198"}},"'// TODO'"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br")])])])],-1),v=s("p",null,[l("APIs like "),s("a",{href:"https://vitest.dev",target:"_blank",rel:"noreferrer"},"Vitest"),l(" are similar cases where you would use a triple slash reference.")],-1),B=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-Yx1mx",id:"tab-XuNO3fX",checked:"checked"}),s("label",{for:"tab-XuNO3fX"},"output"),s("input",{type:"radio",name:"group-Yx1mx",id:"tab-V645NLg"}),s("label",{for:"tab-V645NLg"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const test: any"},"test")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'my tests'"),s("span",{style:{color:"#839496"}},", () "),s("span",{style:{color:"#93A1A1"}},"=>"),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const expect: ExpectStatic",style:{"border-bottom":"solid 2px lightgrey"}},"expect")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#839496"}},")."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"toEqual")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#839496"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const expect: ExpectStatic")])]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"})")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const test: any"},"test")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'my tests'"),s("span",{style:{color:"#657B83"}},", () "),s("span",{style:{color:"#586E75"}},"=>"),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"const expect: ExpectStatic",style:{"border-bottom":"solid 2px lightgrey"}},"expect")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#657B83"}},")."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"any"},"toEqual")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#657B83"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const expect: ExpectStatic")])]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki solarized-dark vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"/// <"),s("span",{style:{color:"#268BD2","font-style":"italic"}},"reference"),s("span",{style:{color:"#586E75","font-style":"italic"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"types"),s("span",{style:{color:"#859900","font-style":"italic"}},"="),s("span",{style:{color:"#2AA198","font-style":"italic"}},'"vitest/globals"'),s("span",{style:{color:"#586E75","font-style":"italic"}}," />")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#586E75","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"test"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'my tests'"),s("span",{style:{color:"#839496"}},", () "),s("span",{style:{color:"#93A1A1","font-weight":"bold"}},"=>"),s("span",{style:{color:"#839496"}}," {")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},"expect"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#839496"}},")."),s("span",{style:{color:"#268BD2"}},"toEqual"),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#839496"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"})")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#839496"}},"```")])])]),s("pre",{class:"shiki solarized-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```ts twoslash")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"/// <"),s("span",{style:{color:"#268BD2","font-style":"italic"}},"reference"),s("span",{style:{color:"#93A1A1","font-style":"italic"}}," types"),s("span",{style:{color:"#859900","font-style":"italic"}},"="),s("span",{style:{color:"#2AA198","font-style":"italic"}},'"vitest/globals"'),s("span",{style:{color:"#93A1A1","font-style":"italic"}}," />")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ---cut---")]),l(` -`),s("span",{class:"line"}),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#268BD2"}},"test"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'my tests'"),s("span",{style:{color:"#657B83"}},", () "),s("span",{style:{color:"#586E75","font-weight":"bold"}},"=>"),s("span",{style:{color:"#657B83"}}," {")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},"expect"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#657B83"}},")."),s("span",{style:{color:"#268BD2"}},"toEqual"),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"'hello'"),s("span",{style:{color:"#657B83"}},")")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1","font-style":"italic"}},"// ^?")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"})")]),l(` -`),s("span",{class:"line"},[s("span",{style:{color:"#657B83"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1);function A(w,D,k,C,x,_){const e=o;return n(),t("div",null,[r,c(e,{readTime:"1",words:"230"}),p,y,d,f,u,g,m,h,b,v,B])}const O=a(i,[["render",A]]);export{T as __pageData,O as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.a1a99084.js b/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.a1a99084.js new file mode 100644 index 00000000..4a32ad18 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.a1a99084.js @@ -0,0 +1,45 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as r,k as s,a as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"@types","description":"Using external libraries with Twoslash code examples.","frontmatter":{"description":"Using external libraries with Twoslash code examples.","title":"@types"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/types.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/types.md","lastUpdated":1699051935000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/types.md"},i=s("h1",{id:"types",tabindex:"-1"},[l("@types "),s("a",{class:"header-anchor",href:"#types","aria-label":'Permalink to "@types"'},"​")],-1),p=s("p",null,"For most examples, you probably need to import external libraries into your code examples.",-1),y=s("p",null,[l("Twoslash works by faking a virtual file system over your existing file system. This means any "),s("code",null,"@types"),l(" or libraries with TypeScript definitions should work out of the box with no config.")],-1),d=s("h2",{id:"local-sources",tabindex:"-1"},[l("Local Sources "),s("a",{class:"header-anchor",href:"#local-sources","aria-label":'Permalink to "Local Sources"'},"​")],-1),u=s("p",null,"Simply import locally installed libraries and Twoslash can pick up types:",-1),f=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-uTL50",id:"tab-H4mhQk_",checked:"checked"}),s("label",{for:"tab-H4mhQk_"},"output"),s("input",{type:"radio",name:"group-uTL50",id:"tab-Fh7cjUz"}),s("label",{for:"tab-Fh7cjUz"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const config: UserConfig",style:{"border-bottom":"solid 2px lightgrey"}},"config")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#ADBAC7"}},"({})")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const config: UserConfig")])]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"const config: UserConfig"},"config")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const config: UserConfig",style:{"border-bottom":"solid 2px lightgrey"}},"config")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({})")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const config: UserConfig")])]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:"const config: UserConfig"},"config")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," { defineConfig } "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"config"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"defineConfig"),s("span",{style:{color:"#ADBAC7"}},"({})")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},"config")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," { defineConfig } "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"config"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"defineConfig"),s("span",{style:{color:"#24292E"}},"({})")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," config")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br")])])])],-1),m=s("h2",{id:"globals",tabindex:"-1"},[l("Globals "),s("a",{class:"header-anchor",href:"#globals","aria-label":'Permalink to "Globals"'},"​")],-1),g=s("p",null,[l("Setting up globals is a little bit more complex, but not drastically. You need to use the "),s("a",{href:"https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-",target:"_blank",rel:"noreferrer"},"triple slash reference"),l(" which adds a particular library to the global scope.")],-1),h=s("p",null,"For example, setting up Node imports and globals etc.",-1),b=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-VHYDd",id:"tab-uOA6RMx",checked:"checked"}),s("label",{for:"tab-uOA6RMx"},"output"),s("input",{type:"radio",name:"group-VHYDd",id:"tab-XchB1nX"}),s("label",{for:"tab-XchB1nX"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void +import writeFileSync`},"writeFileSync"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'fs'")]),s("div",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions | undefined): void +import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'myfile.txt'"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},"'// TODO'"),s("span",{style:{color:"#ADBAC7"}},")")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void +import writeFileSync`},"writeFileSync"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'fs'")]),s("div",{class:"line"},[s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions | undefined): void +import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'myfile.txt'"),s("span",{style:{color:"#24292E"}},", "),s("span",{style:{color:"#032F62"}},"'// TODO'"),s("span",{style:{color:"#24292E"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// <"),s("span",{style:{color:"#8DDB8C"}},"reference"),s("span",{style:{color:"#768390"}}," "),s("span",{style:{color:"#6CB6FF"}},"types"),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#96D0FF"}},'"node"'),s("span",{style:{color:"#768390"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," { writeFileSync } "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'fs'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},"writeFileSync"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'myfile.txt'"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},"'// TODO'"),s("span",{style:{color:"#ADBAC7"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"/// <"),s("span",{style:{color:"#22863A"}},"reference"),s("span",{style:{color:"#6A737D"}}," "),s("span",{style:{color:"#6F42C1"}},"types"),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#032F62"}},'"node"'),s("span",{style:{color:"#6A737D"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," { writeFileSync } "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'fs'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6F42C1"}},"writeFileSync"),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'myfile.txt'"),s("span",{style:{color:"#24292E"}},", "),s("span",{style:{color:"#032F62"}},"'// TODO'"),s("span",{style:{color:"#24292E"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br")])])])],-1),D=s("p",null,[l("APIs like "),s("a",{href:"https://vitest.dev",target:"_blank",rel:"noreferrer"},"Vitest"),l(" are similar cases where you would use a triple slash reference.")],-1),A=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-SKXyI",id:"tab-IahiLSH",checked:"checked"}),s("label",{for:"tab-IahiLSH"},"output"),s("input",{type:"radio",name:"group-SKXyI",id:"tab-csOVfln"}),s("label",{for:"tab-csOVfln"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"const test: any"},"test")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'my tests'"),s("span",{style:{color:"#ADBAC7"}},", () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"const expect: ExpectStatic",style:{"border-bottom":"solid 2px lightgrey"}},"expect")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'hello'"),s("span",{style:{color:"#ADBAC7"}},")."),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"any"},"toEqual")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'hello'"),s("span",{style:{color:"#ADBAC7"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const expect: ExpectStatic")])]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"})")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"const test: any"},"test")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'my tests'"),s("span",{style:{color:"#24292E"}},", () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"const expect: ExpectStatic",style:{"border-bottom":"solid 2px lightgrey"}},"expect")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'hello'"),s("span",{style:{color:"#24292E"}},")."),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"any"},"toEqual")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'hello'"),s("span",{style:{color:"#24292E"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const expect: ExpectStatic")])]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// <"),s("span",{style:{color:"#8DDB8C"}},"reference"),s("span",{style:{color:"#768390"}}," "),s("span",{style:{color:"#6CB6FF"}},"types"),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#96D0FF"}},'"vitest/globals"'),s("span",{style:{color:"#768390"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},"test"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'my tests'"),s("span",{style:{color:"#ADBAC7"}},", () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#ADBAC7"}}," {")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"expect"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'hello'"),s("span",{style:{color:"#ADBAC7"}},")."),s("span",{style:{color:"#DCBDFB"}},"toEqual"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'hello'"),s("span",{style:{color:"#ADBAC7"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"})")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"/// <"),s("span",{style:{color:"#22863A"}},"reference"),s("span",{style:{color:"#6A737D"}}," "),s("span",{style:{color:"#6F42C1"}},"types"),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#032F62"}},'"vitest/globals"'),s("span",{style:{color:"#6A737D"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6F42C1"}},"test"),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'my tests'"),s("span",{style:{color:"#24292E"}},", () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," {")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"expect"),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'hello'"),s("span",{style:{color:"#24292E"}},")."),s("span",{style:{color:"#6F42C1"}},"toEqual"),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'hello'"),s("span",{style:{color:"#24292E"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"})")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1);function C(F,v,B,w,E,k){const e=o;return n(),t("div",null,[i,r(e,{readTime:"1",words:"230"}),p,y,d,u,f,m,g,h,b,D,A])}const O=a(c,[["render",C]]);export{T as __pageData,O as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.a1a99084.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.a1a99084.lean.js new file mode 100644 index 00000000..4a32ad18 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_api_types.md.a1a99084.lean.js @@ -0,0 +1,45 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as r,k as s,a as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"@types","description":"Using external libraries with Twoslash code examples.","frontmatter":{"description":"Using external libraries with Twoslash code examples.","title":"@types"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/api/types.md","filePath":"application/vitepress-plugin-shiki-twoslash/api/types.md","lastUpdated":1699051935000}'),c={name:"application/vitepress-plugin-shiki-twoslash/api/types.md"},i=s("h1",{id:"types",tabindex:"-1"},[l("@types "),s("a",{class:"header-anchor",href:"#types","aria-label":'Permalink to "@types"'},"​")],-1),p=s("p",null,"For most examples, you probably need to import external libraries into your code examples.",-1),y=s("p",null,[l("Twoslash works by faking a virtual file system over your existing file system. This means any "),s("code",null,"@types"),l(" or libraries with TypeScript definitions should work out of the box with no config.")],-1),d=s("h2",{id:"local-sources",tabindex:"-1"},[l("Local Sources "),s("a",{class:"header-anchor",href:"#local-sources","aria-label":'Permalink to "Local Sources"'},"​")],-1),u=s("p",null,"Simply import locally installed libraries and Twoslash can pick up types:",-1),f=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-uTL50",id:"tab-H4mhQk_",checked:"checked"}),s("label",{for:"tab-H4mhQk_"},"output"),s("input",{type:"radio",name:"group-uTL50",id:"tab-Fh7cjUz"}),s("label",{for:"tab-Fh7cjUz"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:"const config: UserConfig",style:{"border-bottom":"solid 2px lightgrey"}},"config")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#ADBAC7"}},"({})")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const config: UserConfig")])]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"const config: UserConfig"},"config")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:"const config: UserConfig",style:{"border-bottom":"solid 2px lightgrey"}},"config")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({})")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const config: UserConfig")])]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:"const config: UserConfig"},"config")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," { defineConfig } "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"config"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"defineConfig"),s("span",{style:{color:"#ADBAC7"}},"({})")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},"config")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," { defineConfig } "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"config"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"defineConfig"),s("span",{style:{color:"#24292E"}},"({})")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," config")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br")])])])],-1),m=s("h2",{id:"globals",tabindex:"-1"},[l("Globals "),s("a",{class:"header-anchor",href:"#globals","aria-label":'Permalink to "Globals"'},"​")],-1),g=s("p",null,[l("Setting up globals is a little bit more complex, but not drastically. You need to use the "),s("a",{href:"https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-",target:"_blank",rel:"noreferrer"},"triple slash reference"),l(" which adds a particular library to the global scope.")],-1),h=s("p",null,"For example, setting up Node imports and globals etc.",-1),b=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-VHYDd",id:"tab-uOA6RMx",checked:"checked"}),s("label",{for:"tab-uOA6RMx"},"output"),s("input",{type:"radio",name:"group-VHYDd",id:"tab-XchB1nX"}),s("label",{for:"tab-XchB1nX"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void +import writeFileSync`},"writeFileSync"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'fs'")]),s("div",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions | undefined): void +import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'myfile.txt'"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},"'// TODO'"),s("span",{style:{color:"#ADBAC7"}},")")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void +import writeFileSync`},"writeFileSync"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'fs'")]),s("div",{class:"line"},[s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) writeFileSync(file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions | undefined): void +import writeFileSync`},"writeFileSync")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'myfile.txt'"),s("span",{style:{color:"#24292E"}},", "),s("span",{style:{color:"#032F62"}},"'// TODO'"),s("span",{style:{color:"#24292E"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// <"),s("span",{style:{color:"#8DDB8C"}},"reference"),s("span",{style:{color:"#768390"}}," "),s("span",{style:{color:"#6CB6FF"}},"types"),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#96D0FF"}},'"node"'),s("span",{style:{color:"#768390"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," { writeFileSync } "),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'fs'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},"writeFileSync"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'myfile.txt'"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},"'// TODO'"),s("span",{style:{color:"#ADBAC7"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"/// <"),s("span",{style:{color:"#22863A"}},"reference"),s("span",{style:{color:"#6A737D"}}," "),s("span",{style:{color:"#6F42C1"}},"types"),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#032F62"}},'"node"'),s("span",{style:{color:"#6A737D"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," { writeFileSync } "),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'fs'")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6F42C1"}},"writeFileSync"),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'myfile.txt'"),s("span",{style:{color:"#24292E"}},", "),s("span",{style:{color:"#032F62"}},"'// TODO'"),s("span",{style:{color:"#24292E"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br")])])])],-1),D=s("p",null,[l("APIs like "),s("a",{href:"https://vitest.dev",target:"_blank",rel:"noreferrer"},"Vitest"),l(" are similar cases where you would use a triple slash reference.")],-1),A=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-SKXyI",id:"tab-IahiLSH",checked:"checked"}),s("label",{for:"tab-IahiLSH"},"output"),s("input",{type:"radio",name:"group-SKXyI",id:"tab-csOVfln"}),s("label",{for:"tab-csOVfln"},"markdown")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"const test: any"},"test")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'my tests'"),s("span",{style:{color:"#ADBAC7"}},", () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"const expect: ExpectStatic",style:{"border-bottom":"solid 2px lightgrey"}},"expect")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'hello'"),s("span",{style:{color:"#ADBAC7"}},")."),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"any"},"toEqual")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'hello'"),s("span",{style:{color:"#ADBAC7"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const expect: ExpectStatic")])]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"})")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"const test: any"},"test")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'my tests'"),s("span",{style:{color:"#24292E"}},", () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"const expect: ExpectStatic",style:{"border-bottom":"solid 2px lightgrey"}},"expect")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'hello'"),s("span",{style:{color:"#24292E"}},")."),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"any"},"toEqual")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'hello'"),s("span",{style:{color:"#24292E"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l("const expect: ExpectStatic")])]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])]),s("div",{class:"language-md vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"md"),s("pre",{class:"shiki github-dark-dimmed vp-code-dark"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// <"),s("span",{style:{color:"#8DDB8C"}},"reference"),s("span",{style:{color:"#768390"}}," "),s("span",{style:{color:"#6CB6FF"}},"types"),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#96D0FF"}},'"vitest/globals"'),s("span",{style:{color:"#768390"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// ---cut---")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},"test"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'my tests'"),s("span",{style:{color:"#ADBAC7"}},", () "),s("span",{style:{color:"#F47067"}},"=>"),s("span",{style:{color:"#ADBAC7"}}," {")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"expect"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'hello'"),s("span",{style:{color:"#ADBAC7"}},")."),s("span",{style:{color:"#DCBDFB"}},"toEqual"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"'hello'"),s("span",{style:{color:"#ADBAC7"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"})")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"```")])])]),s("pre",{class:"shiki github-light vp-code-light"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```ts twoslash")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"/// <"),s("span",{style:{color:"#22863A"}},"reference"),s("span",{style:{color:"#6A737D"}}," "),s("span",{style:{color:"#6F42C1"}},"types"),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#032F62"}},'"vitest/globals"'),s("span",{style:{color:"#6A737D"}}," />")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// ---cut---")]),l(` +`),s("span",{class:"line"}),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#6F42C1"}},"test"),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'my tests'"),s("span",{style:{color:"#24292E"}},", () "),s("span",{style:{color:"#D73A49"}},"=>"),s("span",{style:{color:"#24292E"}}," {")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},"expect"),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'hello'"),s("span",{style:{color:"#24292E"}},")."),s("span",{style:{color:"#6F42C1"}},"toEqual"),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"'hello'"),s("span",{style:{color:"#24292E"}},")")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// ^?")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"})")]),l(` +`),s("span",{class:"line"},[s("span",{style:{color:"#24292E"}},"```")])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br"),s("span",{class:"line-number"},"5"),s("br"),s("span",{class:"line-number"},"6"),s("br"),s("span",{class:"line-number"},"7"),s("br"),s("span",{class:"line-number"},"8"),s("br"),s("span",{class:"line-number"},"9"),s("br")])])])],-1);function C(F,v,B,w,E,k){const e=o;return n(),t("div",null,[i,r(e,{readTime:"1",words:"230"}),p,y,d,u,f,m,g,h,b,D,A])}const O=a(c,[["render",C]]);export{T as __pageData,O as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.52b87b95.js b/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.52b87b95.js new file mode 100644 index 00000000..4d16afdb --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.52b87b95.js @@ -0,0 +1,591 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as p,H as c,k as s,a as r,Q as o}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Compiler Flags","description":"","frontmatter":{"title":"Compiler Flags"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/config/flags.md","filePath":"application/vitepress-plugin-shiki-twoslash/config/flags.md","lastUpdated":1699051935000}'),i={name:"application/vitepress-plugin-shiki-twoslash/config/flags.md"},t=s("h1",{id:"compiler-flags",tabindex:"-1"},[r("Compiler Flags "),s("a",{class:"header-anchor",href:"#compiler-flags","aria-label":'Permalink to "Compiler Flags"'},"​")],-1),b=o(`
    // @allowJs
    +Allow JavaScript files to be a part of your program. Use the \`checkJS\` option to get errors from these files..
    +
    +// @allowSyntheticDefaultImports
    +Allow 'import x from y' when a module doesn't have a default export..
    +
    +// @allowUmdGlobalAccess
    +Allow accessing UMD globals from modules..
    +
    +// @allowUnreachableCode
    +Disable error reporting for unreachable code..
    +
    +// @allowUnusedLabels
    +Disable error reporting for unused labels..
    +
    +// @alwaysStrict
    +Ensure 'use strict' is always emitted..
    +
    +// @assumeChangesOnlyAffectDirectDependencies
    +Have recompiles in projects that use \`incremental\` and \`watch\` mode assume that changes within a file will only affect files directly depending on it..
    +
    +// @baseUrl
    +Specify the base directory to resolve non-relative module names..
    +
    +// @charset
    +No longer supported. In early versions, manually set the text encoding for reading files..
    +
    +// @checkJs
    +Enable error reporting in type-checked JavaScript files..
    +
    +// @composite
    +Enable constraints that allow a TypeScript project to be used with project references..
    +
    +// @declaration
    +Generate .d.ts files from TypeScript and JavaScript files in your project..
    +
    +// @declarationDir
    +Specify the output directory for generated declaration files..
    +
    +// @declarationMap
    +Create sourcemaps for d.ts files..
    +
    +// @diagnostics
    +Output compiler performance information after building..
    +
    +// @disableReferencedProjectLoad
    +Reduce the number of projects loaded automatically by TypeScript..
    +
    +// @disableSizeLimit
    +Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
    +
    +// @disableSolutionSearching
    +Opt a project out of multi-project reference checking when editing..
    +
    +// @disableSourceOfProjectReferenceRedirect
    +Disable preferring source files instead of declaration files when referencing composite projects.
    +
    +// @downlevelIteration
    +Emit more compliant, but verbose and less performant JavaScript for iteration..
    +
    +// @emitBOM
    +Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
    +
    +// @emitDeclarationOnly
    +Only output d.ts files and not JavaScript files..
    +
    +// @emitDecoratorMetadata
    +Emit design-type metadata for decorated declarations in source files..
    +
    +// @esModuleInterop
    +Emit additional JavaScript to ease support for importing CommonJS modules. This enables \`allowSyntheticDefaultImports\` for type compatibility..
    +
    +// @exactOptionalPropertyTypes
    +Interpret optional property types as written, rather than adding 'undefined'..
    +
    +// @experimentalDecorators
    +Enable experimental support for TC39 stage 2 draft decorators..
    +
    +// @explainFiles
    +Print files read during the compilation including why it was included..
    +
    +// @extendedDiagnostics
    +Output more detailed compiler performance information after building..
    +
    +// @forceConsistentCasingInFileNames
    +Ensure that casing is correct in imports..
    +
    +// @generateCpuProfile
    +Emit a v8 CPU profile of the compiler run for debugging..
    +
    +// @importHelpers
    +Allow importing helper functions from tslib once per project, instead of including them per-file..
    +
    +// @importsNotUsedAsValues
    +Specify emit/checking behavior for imports that are only used for types.
    +
    +// @incremental
    +Enable incremental compilation.
    +
    +// @inlineSourceMap
    +Include sourcemap files inside the emitted JavaScript..
    +
    +// @inlineSources
    +Include source code in the sourcemaps inside the emitted JavaScript..
    +
    +// @isolatedModules
    +Ensure that each file can be safely transpiled without relying on other imports..
    +
    +// @jsx
    +Specify what JSX code is generated..
    +
    +// @jsxFactory
    +Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
    +
    +// @jsxFragmentFactory
    +Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
    +
    +// @jsxImportSource
    +Specify module specifier used to import the JSX factory functions when using \`jsx: react-jsx*\`.\`.
    +
    +// @keyofStringsOnly
    +Make keyof only return strings instead of string, numbers or symbols. Legacy option..
    +
    +// @lib
    +Specify a set of bundled library declaration files that describe the target runtime environment..
    +
    +// @listEmittedFiles
    +Print the names of emitted files after a compilation..
    +
    +// @listFiles
    +Print all of the files read during the compilation..
    +
    +// @mapRoot
    +Specify the location where debugger should locate map files instead of generated locations..
    +
    +// @maxNodeModuleJsDepth
    +Specify the maximum folder depth used for checking JavaScript files from \`node_modules\`. Only applicable with \`allowJs\`..
    +
    +// @module
    +Specify what module code is generated..
    +
    +// @moduleResolution
    +Specify how TypeScript looks up a file from a given module specifier..
    +
    +// @newLine
    +Set the newline character for emitting files..
    +
    +// @noEmit
    +Disable emitting file from a compilation..
    +
    +// @noEmitHelpers
    +Disable generating custom helper functions like \`__extends\` in compiled output..
    +
    +// @noEmitOnError
    +Disable emitting files if any type checking errors are reported..
    +
    +// @noErrorTruncation
    +Disable truncating types in error messages..
    +
    +// @noFallthroughCasesInSwitch
    +Enable error reporting for fallthrough cases in switch statements..
    +
    +// @noImplicitAny
    +Enable error reporting for expressions and declarations with an implied \`any\` type...
    +
    +// @noImplicitOverride
    +Add \`undefined\` to a type when accessed using an index..
    +
    +// @noImplicitReturns
    +Enable error reporting for codepaths that do not explicitly return in a function..
    +
    +// @noImplicitThis
    +Enable error reporting when \`this\` is given the type \`any\`..
    +
    +// @noImplicitUseStrict
    +Disable adding 'use strict' directives in emitted JavaScript files..
    +
    +// @noLib
    +Disable including any library files, including the default lib.d.ts..
    +
    +// @noPropertyAccessFromIndexSignature
    +Enforces using indexed accessors for keys declared using an indexed type.
    +
    +// @noResolve
    +Disallow \`import\`s, \`require\`s or \`\`s from expanding the number of files TypeScript should add to a project..
    +
    +// @noStrictGenericChecks
    +Disable strict checking of generic signatures in function types..
    +
    +// @noUncheckedIndexedAccess
    +Include 'undefined' in index signature results.
    +
    +// @noUnusedLocals
    +Enable error reporting when a local variables aren't read..
    +
    +// @noUnusedParameters
    +Raise an error when a function parameter isn't read.
    +
    +// @out
    +Deprecated setting. Use \`outFile\` instead..
    +
    +// @outDir
    +Specify an output folder for all emitted files..
    +
    +// @outFile
    +Specify a file that bundles all outputs into one JavaScript file. If \`declaration\` is true, also designates a file that bundles all .d.ts output..
    +
    +// @paths
    +Specify a set of entries that re-map imports to additional lookup locations..
    +
    +// @plugins
    +List of language service plugins..
    +
    +// @preserveConstEnums
    +Disable erasing \`const enum\` declarations in generated code..
    +
    +// @preserveSymlinks
    +Disable resolving symlinks to their realpath. This correlates to the same flag in node..
    +
    +// @preserveWatchOutput
    +Disable wiping the console in watch mode.
    +
    +// @pretty
    +Enable color and formatting in output to make compiler errors easier to read.
    +
    +// @reactNamespace
    +Specify the object invoked for \`createElement\`. This only applies when targeting \`react\` JSX emit..
    +
    +// @removeComments
    +Disable emitting comments..
    +
    +// @resolveJsonModule
    +Enable importing .json files.
    +
    +// @rootDir
    +Specify the root folder within your source files..
    +
    +// @rootDirs
    +Allow multiple folders to be treated as one when resolving modules..
    +
    +// @skipDefaultLibCheck
    +Skip type checking .d.ts files that are included with TypeScript..
    +
    +// @skipLibCheck
    +Skip type checking all .d.ts files..
    +
    +// @sourceMap
    +Create source map files for emitted JavaScript files..
    +
    +// @sourceRoot
    +Specify the root path for debuggers to find the reference source code..
    +
    +// @strict
    +Enable all strict type-checking options..
    +
    +// @strictBindCallApply
    +Check that the arguments for \`bind\`, \`call\`, and \`apply\` methods match the original function..
    +
    +// @strictFunctionTypes
    +When assigning functions, check to ensure parameters and the return values are subtype-compatible..
    +
    +// @strictNullChecks
    +When type checking, take into account \`null\` and \`undefined\`..
    +
    +// @strictPropertyInitialization
    +Check for class properties that are declared but not set in the constructor..
    +
    +// @stripInternal
    +Disable emitting declarations that have \`@internal\` in their JSDoc comments..
    +
    +// @suppressExcessPropertyErrors
    +Disable reporting of excess property errors during the creation of object literals..
    +
    +// @suppressImplicitAnyIndexErrors
    +Suppress \`noImplicitAny\` errors when indexing objects that lack index signatures..
    +
    +// @target
    +Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
    +
    +// @traceResolution
    +Log paths used during the \`moduleResolution\` process..
    +
    +// @tsBuildInfoFile
    +Specify the folder for .tsbuildinfo incremental compilation files..
    +
    +// @typeRoots
    +Specify multiple folders that act like \`./node_modules/@types\`..
    +
    +// @types
    +Specify type package names to be included without being referenced in a source file..
    +
    +// @useDefineForClassFields
    +Emit ECMAScript-standard-compliant class fields..
    +
    +// @useUnknownInCatchVariables
    +Type catch clause variables as 'unknown' instead of 'any'..
    // @allowJs
    +Allow JavaScript files to be a part of your program. Use the \`checkJS\` option to get errors from these files..
    +
    +// @allowSyntheticDefaultImports
    +Allow 'import x from y' when a module doesn't have a default export..
    +
    +// @allowUmdGlobalAccess
    +Allow accessing UMD globals from modules..
    +
    +// @allowUnreachableCode
    +Disable error reporting for unreachable code..
    +
    +// @allowUnusedLabels
    +Disable error reporting for unused labels..
    +
    +// @alwaysStrict
    +Ensure 'use strict' is always emitted..
    +
    +// @assumeChangesOnlyAffectDirectDependencies
    +Have recompiles in projects that use \`incremental\` and \`watch\` mode assume that changes within a file will only affect files directly depending on it..
    +
    +// @baseUrl
    +Specify the base directory to resolve non-relative module names..
    +
    +// @charset
    +No longer supported. In early versions, manually set the text encoding for reading files..
    +
    +// @checkJs
    +Enable error reporting in type-checked JavaScript files..
    +
    +// @composite
    +Enable constraints that allow a TypeScript project to be used with project references..
    +
    +// @declaration
    +Generate .d.ts files from TypeScript and JavaScript files in your project..
    +
    +// @declarationDir
    +Specify the output directory for generated declaration files..
    +
    +// @declarationMap
    +Create sourcemaps for d.ts files..
    +
    +// @diagnostics
    +Output compiler performance information after building..
    +
    +// @disableReferencedProjectLoad
    +Reduce the number of projects loaded automatically by TypeScript..
    +
    +// @disableSizeLimit
    +Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
    +
    +// @disableSolutionSearching
    +Opt a project out of multi-project reference checking when editing..
    +
    +// @disableSourceOfProjectReferenceRedirect
    +Disable preferring source files instead of declaration files when referencing composite projects.
    +
    +// @downlevelIteration
    +Emit more compliant, but verbose and less performant JavaScript for iteration..
    +
    +// @emitBOM
    +Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
    +
    +// @emitDeclarationOnly
    +Only output d.ts files and not JavaScript files..
    +
    +// @emitDecoratorMetadata
    +Emit design-type metadata for decorated declarations in source files..
    +
    +// @esModuleInterop
    +Emit additional JavaScript to ease support for importing CommonJS modules. This enables \`allowSyntheticDefaultImports\` for type compatibility..
    +
    +// @exactOptionalPropertyTypes
    +Interpret optional property types as written, rather than adding 'undefined'..
    +
    +// @experimentalDecorators
    +Enable experimental support for TC39 stage 2 draft decorators..
    +
    +// @explainFiles
    +Print files read during the compilation including why it was included..
    +
    +// @extendedDiagnostics
    +Output more detailed compiler performance information after building..
    +
    +// @forceConsistentCasingInFileNames
    +Ensure that casing is correct in imports..
    +
    +// @generateCpuProfile
    +Emit a v8 CPU profile of the compiler run for debugging..
    +
    +// @importHelpers
    +Allow importing helper functions from tslib once per project, instead of including them per-file..
    +
    +// @importsNotUsedAsValues
    +Specify emit/checking behavior for imports that are only used for types.
    +
    +// @incremental
    +Enable incremental compilation.
    +
    +// @inlineSourceMap
    +Include sourcemap files inside the emitted JavaScript..
    +
    +// @inlineSources
    +Include source code in the sourcemaps inside the emitted JavaScript..
    +
    +// @isolatedModules
    +Ensure that each file can be safely transpiled without relying on other imports..
    +
    +// @jsx
    +Specify what JSX code is generated..
    +
    +// @jsxFactory
    +Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
    +
    +// @jsxFragmentFactory
    +Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
    +
    +// @jsxImportSource
    +Specify module specifier used to import the JSX factory functions when using \`jsx: react-jsx*\`.\`.
    +
    +// @keyofStringsOnly
    +Make keyof only return strings instead of string, numbers or symbols. Legacy option..
    +
    +// @lib
    +Specify a set of bundled library declaration files that describe the target runtime environment..
    +
    +// @listEmittedFiles
    +Print the names of emitted files after a compilation..
    +
    +// @listFiles
    +Print all of the files read during the compilation..
    +
    +// @mapRoot
    +Specify the location where debugger should locate map files instead of generated locations..
    +
    +// @maxNodeModuleJsDepth
    +Specify the maximum folder depth used for checking JavaScript files from \`node_modules\`. Only applicable with \`allowJs\`..
    +
    +// @module
    +Specify what module code is generated..
    +
    +// @moduleResolution
    +Specify how TypeScript looks up a file from a given module specifier..
    +
    +// @newLine
    +Set the newline character for emitting files..
    +
    +// @noEmit
    +Disable emitting file from a compilation..
    +
    +// @noEmitHelpers
    +Disable generating custom helper functions like \`__extends\` in compiled output..
    +
    +// @noEmitOnError
    +Disable emitting files if any type checking errors are reported..
    +
    +// @noErrorTruncation
    +Disable truncating types in error messages..
    +
    +// @noFallthroughCasesInSwitch
    +Enable error reporting for fallthrough cases in switch statements..
    +
    +// @noImplicitAny
    +Enable error reporting for expressions and declarations with an implied \`any\` type...
    +
    +// @noImplicitOverride
    +Add \`undefined\` to a type when accessed using an index..
    +
    +// @noImplicitReturns
    +Enable error reporting for codepaths that do not explicitly return in a function..
    +
    +// @noImplicitThis
    +Enable error reporting when \`this\` is given the type \`any\`..
    +
    +// @noImplicitUseStrict
    +Disable adding 'use strict' directives in emitted JavaScript files..
    +
    +// @noLib
    +Disable including any library files, including the default lib.d.ts..
    +
    +// @noPropertyAccessFromIndexSignature
    +Enforces using indexed accessors for keys declared using an indexed type.
    +
    +// @noResolve
    +Disallow \`import\`s, \`require\`s or \`\`s from expanding the number of files TypeScript should add to a project..
    +
    +// @noStrictGenericChecks
    +Disable strict checking of generic signatures in function types..
    +
    +// @noUncheckedIndexedAccess
    +Include 'undefined' in index signature results.
    +
    +// @noUnusedLocals
    +Enable error reporting when a local variables aren't read..
    +
    +// @noUnusedParameters
    +Raise an error when a function parameter isn't read.
    +
    +// @out
    +Deprecated setting. Use \`outFile\` instead..
    +
    +// @outDir
    +Specify an output folder for all emitted files..
    +
    +// @outFile
    +Specify a file that bundles all outputs into one JavaScript file. If \`declaration\` is true, also designates a file that bundles all .d.ts output..
    +
    +// @paths
    +Specify a set of entries that re-map imports to additional lookup locations..
    +
    +// @plugins
    +List of language service plugins..
    +
    +// @preserveConstEnums
    +Disable erasing \`const enum\` declarations in generated code..
    +
    +// @preserveSymlinks
    +Disable resolving symlinks to their realpath. This correlates to the same flag in node..
    +
    +// @preserveWatchOutput
    +Disable wiping the console in watch mode.
    +
    +// @pretty
    +Enable color and formatting in output to make compiler errors easier to read.
    +
    +// @reactNamespace
    +Specify the object invoked for \`createElement\`. This only applies when targeting \`react\` JSX emit..
    +
    +// @removeComments
    +Disable emitting comments..
    +
    +// @resolveJsonModule
    +Enable importing .json files.
    +
    +// @rootDir
    +Specify the root folder within your source files..
    +
    +// @rootDirs
    +Allow multiple folders to be treated as one when resolving modules..
    +
    +// @skipDefaultLibCheck
    +Skip type checking .d.ts files that are included with TypeScript..
    +
    +// @skipLibCheck
    +Skip type checking all .d.ts files..
    +
    +// @sourceMap
    +Create source map files for emitted JavaScript files..
    +
    +// @sourceRoot
    +Specify the root path for debuggers to find the reference source code..
    +
    +// @strict
    +Enable all strict type-checking options..
    +
    +// @strictBindCallApply
    +Check that the arguments for \`bind\`, \`call\`, and \`apply\` methods match the original function..
    +
    +// @strictFunctionTypes
    +When assigning functions, check to ensure parameters and the return values are subtype-compatible..
    +
    +// @strictNullChecks
    +When type checking, take into account \`null\` and \`undefined\`..
    +
    +// @strictPropertyInitialization
    +Check for class properties that are declared but not set in the constructor..
    +
    +// @stripInternal
    +Disable emitting declarations that have \`@internal\` in their JSDoc comments..
    +
    +// @suppressExcessPropertyErrors
    +Disable reporting of excess property errors during the creation of object literals..
    +
    +// @suppressImplicitAnyIndexErrors
    +Suppress \`noImplicitAny\` errors when indexing objects that lack index signatures..
    +
    +// @target
    +Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
    +
    +// @traceResolution
    +Log paths used during the \`moduleResolution\` process..
    +
    +// @tsBuildInfoFile
    +Specify the folder for .tsbuildinfo incremental compilation files..
    +
    +// @typeRoots
    +Specify multiple folders that act like \`./node_modules/@types\`..
    +
    +// @types
    +Specify type package names to be included without being referenced in a source file..
    +
    +// @useDefineForClassFields
    +Emit ECMAScript-standard-compliant class fields..
    +
    +// @useUnknownInCatchVariables
    +Type catch clause variables as 'unknown' instead of 'any'..
    `,1);function y(d,u,m,f,h,g){const n=a;return l(),p("div",null,[t,c(n,{readTime:"7",words:"1.1k"}),b])}const D=e(i,[["render",y]]);export{k as __pageData,D as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.52b87b95.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.52b87b95.lean.js new file mode 100644 index 00000000..20f439e2 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.52b87b95.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as p,H as c,k as s,a as r,Q as o}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Compiler Flags","description":"","frontmatter":{"title":"Compiler Flags"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/config/flags.md","filePath":"application/vitepress-plugin-shiki-twoslash/config/flags.md","lastUpdated":1699051935000}'),i={name:"application/vitepress-plugin-shiki-twoslash/config/flags.md"},t=s("h1",{id:"compiler-flags",tabindex:"-1"},[r("Compiler Flags "),s("a",{class:"header-anchor",href:"#compiler-flags","aria-label":'Permalink to "Compiler Flags"'},"​")],-1),b=o("",1);function y(d,u,m,f,h,g){const n=a;return l(),p("div",null,[t,c(n,{readTime:"7",words:"1.1k"}),b])}const D=e(i,[["render",y]]);export{k as __pageData,D as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.a683705b.js b/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.a683705b.js deleted file mode 100644 index 7c9de8cd..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.a683705b.js +++ /dev/null @@ -1,591 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o as e,c as p,H as r,k as s,a as o,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Compiler Flags","description":"","frontmatter":{"title":"Compiler Flags"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/config/flags.md","filePath":"application/vitepress-plugin-shiki-twoslash/config/flags.md","lastUpdated":1695377563000}'),i={name:"application/vitepress-plugin-shiki-twoslash/config/flags.md"},t=s("h1",{id:"compiler-flags",tabindex:"-1"},[o("Compiler Flags "),s("a",{class:"header-anchor",href:"#compiler-flags","aria-label":'Permalink to "Compiler Flags"'},"​")],-1),y=c(`
    // @allowJs
    -Allow JavaScript files to be a part of your program. Use the \`checkJS\` option to get errors from these files..
    -
    -// @allowSyntheticDefaultImports
    -Allow 'import x from y' when a module doesn't have a default export..
    -
    -// @allowUmdGlobalAccess
    -Allow accessing UMD globals from modules..
    -
    -// @allowUnreachableCode
    -Disable error reporting for unreachable code..
    -
    -// @allowUnusedLabels
    -Disable error reporting for unused labels..
    -
    -// @alwaysStrict
    -Ensure 'use strict' is always emitted..
    -
    -// @assumeChangesOnlyAffectDirectDependencies
    -Have recompiles in projects that use \`incremental\` and \`watch\` mode assume that changes within a file will only affect files directly depending on it..
    -
    -// @baseUrl
    -Specify the base directory to resolve non-relative module names..
    -
    -// @charset
    -No longer supported. In early versions, manually set the text encoding for reading files..
    -
    -// @checkJs
    -Enable error reporting in type-checked JavaScript files..
    -
    -// @composite
    -Enable constraints that allow a TypeScript project to be used with project references..
    -
    -// @declaration
    -Generate .d.ts files from TypeScript and JavaScript files in your project..
    -
    -// @declarationDir
    -Specify the output directory for generated declaration files..
    -
    -// @declarationMap
    -Create sourcemaps for d.ts files..
    -
    -// @diagnostics
    -Output compiler performance information after building..
    -
    -// @disableReferencedProjectLoad
    -Reduce the number of projects loaded automatically by TypeScript..
    -
    -// @disableSizeLimit
    -Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
    -
    -// @disableSolutionSearching
    -Opt a project out of multi-project reference checking when editing..
    -
    -// @disableSourceOfProjectReferenceRedirect
    -Disable preferring source files instead of declaration files when referencing composite projects.
    -
    -// @downlevelIteration
    -Emit more compliant, but verbose and less performant JavaScript for iteration..
    -
    -// @emitBOM
    -Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
    -
    -// @emitDeclarationOnly
    -Only output d.ts files and not JavaScript files..
    -
    -// @emitDecoratorMetadata
    -Emit design-type metadata for decorated declarations in source files..
    -
    -// @esModuleInterop
    -Emit additional JavaScript to ease support for importing CommonJS modules. This enables \`allowSyntheticDefaultImports\` for type compatibility..
    -
    -// @exactOptionalPropertyTypes
    -Interpret optional property types as written, rather than adding 'undefined'..
    -
    -// @experimentalDecorators
    -Enable experimental support for TC39 stage 2 draft decorators..
    -
    -// @explainFiles
    -Print files read during the compilation including why it was included..
    -
    -// @extendedDiagnostics
    -Output more detailed compiler performance information after building..
    -
    -// @forceConsistentCasingInFileNames
    -Ensure that casing is correct in imports..
    -
    -// @generateCpuProfile
    -Emit a v8 CPU profile of the compiler run for debugging..
    -
    -// @importHelpers
    -Allow importing helper functions from tslib once per project, instead of including them per-file..
    -
    -// @importsNotUsedAsValues
    -Specify emit/checking behavior for imports that are only used for types.
    -
    -// @incremental
    -Enable incremental compilation.
    -
    -// @inlineSourceMap
    -Include sourcemap files inside the emitted JavaScript..
    -
    -// @inlineSources
    -Include source code in the sourcemaps inside the emitted JavaScript..
    -
    -// @isolatedModules
    -Ensure that each file can be safely transpiled without relying on other imports..
    -
    -// @jsx
    -Specify what JSX code is generated..
    -
    -// @jsxFactory
    -Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
    -
    -// @jsxFragmentFactory
    -Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
    -
    -// @jsxImportSource
    -Specify module specifier used to import the JSX factory functions when using \`jsx: react-jsx*\`.\`.
    -
    -// @keyofStringsOnly
    -Make keyof only return strings instead of string, numbers or symbols. Legacy option..
    -
    -// @lib
    -Specify a set of bundled library declaration files that describe the target runtime environment..
    -
    -// @listEmittedFiles
    -Print the names of emitted files after a compilation..
    -
    -// @listFiles
    -Print all of the files read during the compilation..
    -
    -// @mapRoot
    -Specify the location where debugger should locate map files instead of generated locations..
    -
    -// @maxNodeModuleJsDepth
    -Specify the maximum folder depth used for checking JavaScript files from \`node_modules\`. Only applicable with \`allowJs\`..
    -
    -// @module
    -Specify what module code is generated..
    -
    -// @moduleResolution
    -Specify how TypeScript looks up a file from a given module specifier..
    -
    -// @newLine
    -Set the newline character for emitting files..
    -
    -// @noEmit
    -Disable emitting file from a compilation..
    -
    -// @noEmitHelpers
    -Disable generating custom helper functions like \`__extends\` in compiled output..
    -
    -// @noEmitOnError
    -Disable emitting files if any type checking errors are reported..
    -
    -// @noErrorTruncation
    -Disable truncating types in error messages..
    -
    -// @noFallthroughCasesInSwitch
    -Enable error reporting for fallthrough cases in switch statements..
    -
    -// @noImplicitAny
    -Enable error reporting for expressions and declarations with an implied \`any\` type...
    -
    -// @noImplicitOverride
    -Add \`undefined\` to a type when accessed using an index..
    -
    -// @noImplicitReturns
    -Enable error reporting for codepaths that do not explicitly return in a function..
    -
    -// @noImplicitThis
    -Enable error reporting when \`this\` is given the type \`any\`..
    -
    -// @noImplicitUseStrict
    -Disable adding 'use strict' directives in emitted JavaScript files..
    -
    -// @noLib
    -Disable including any library files, including the default lib.d.ts..
    -
    -// @noPropertyAccessFromIndexSignature
    -Enforces using indexed accessors for keys declared using an indexed type.
    -
    -// @noResolve
    -Disallow \`import\`s, \`require\`s or \`\`s from expanding the number of files TypeScript should add to a project..
    -
    -// @noStrictGenericChecks
    -Disable strict checking of generic signatures in function types..
    -
    -// @noUncheckedIndexedAccess
    -Include 'undefined' in index signature results.
    -
    -// @noUnusedLocals
    -Enable error reporting when a local variables aren't read..
    -
    -// @noUnusedParameters
    -Raise an error when a function parameter isn't read.
    -
    -// @out
    -Deprecated setting. Use \`outFile\` instead..
    -
    -// @outDir
    -Specify an output folder for all emitted files..
    -
    -// @outFile
    -Specify a file that bundles all outputs into one JavaScript file. If \`declaration\` is true, also designates a file that bundles all .d.ts output..
    -
    -// @paths
    -Specify a set of entries that re-map imports to additional lookup locations..
    -
    -// @plugins
    -List of language service plugins..
    -
    -// @preserveConstEnums
    -Disable erasing \`const enum\` declarations in generated code..
    -
    -// @preserveSymlinks
    -Disable resolving symlinks to their realpath. This correlates to the same flag in node..
    -
    -// @preserveWatchOutput
    -Disable wiping the console in watch mode.
    -
    -// @pretty
    -Enable color and formatting in output to make compiler errors easier to read.
    -
    -// @reactNamespace
    -Specify the object invoked for \`createElement\`. This only applies when targeting \`react\` JSX emit..
    -
    -// @removeComments
    -Disable emitting comments..
    -
    -// @resolveJsonModule
    -Enable importing .json files.
    -
    -// @rootDir
    -Specify the root folder within your source files..
    -
    -// @rootDirs
    -Allow multiple folders to be treated as one when resolving modules..
    -
    -// @skipDefaultLibCheck
    -Skip type checking .d.ts files that are included with TypeScript..
    -
    -// @skipLibCheck
    -Skip type checking all .d.ts files..
    -
    -// @sourceMap
    -Create source map files for emitted JavaScript files..
    -
    -// @sourceRoot
    -Specify the root path for debuggers to find the reference source code..
    -
    -// @strict
    -Enable all strict type-checking options..
    -
    -// @strictBindCallApply
    -Check that the arguments for \`bind\`, \`call\`, and \`apply\` methods match the original function..
    -
    -// @strictFunctionTypes
    -When assigning functions, check to ensure parameters and the return values are subtype-compatible..
    -
    -// @strictNullChecks
    -When type checking, take into account \`null\` and \`undefined\`..
    -
    -// @strictPropertyInitialization
    -Check for class properties that are declared but not set in the constructor..
    -
    -// @stripInternal
    -Disable emitting declarations that have \`@internal\` in their JSDoc comments..
    -
    -// @suppressExcessPropertyErrors
    -Disable reporting of excess property errors during the creation of object literals..
    -
    -// @suppressImplicitAnyIndexErrors
    -Suppress \`noImplicitAny\` errors when indexing objects that lack index signatures..
    -
    -// @target
    -Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
    -
    -// @traceResolution
    -Log paths used during the \`moduleResolution\` process..
    -
    -// @tsBuildInfoFile
    -Specify the folder for .tsbuildinfo incremental compilation files..
    -
    -// @typeRoots
    -Specify multiple folders that act like \`./node_modules/@types\`..
    -
    -// @types
    -Specify type package names to be included without being referenced in a source file..
    -
    -// @useDefineForClassFields
    -Emit ECMAScript-standard-compliant class fields..
    -
    -// @useUnknownInCatchVariables
    -Type catch clause variables as 'unknown' instead of 'any'..
    // @allowJs
    -Allow JavaScript files to be a part of your program. Use the \`checkJS\` option to get errors from these files..
    -
    -// @allowSyntheticDefaultImports
    -Allow 'import x from y' when a module doesn't have a default export..
    -
    -// @allowUmdGlobalAccess
    -Allow accessing UMD globals from modules..
    -
    -// @allowUnreachableCode
    -Disable error reporting for unreachable code..
    -
    -// @allowUnusedLabels
    -Disable error reporting for unused labels..
    -
    -// @alwaysStrict
    -Ensure 'use strict' is always emitted..
    -
    -// @assumeChangesOnlyAffectDirectDependencies
    -Have recompiles in projects that use \`incremental\` and \`watch\` mode assume that changes within a file will only affect files directly depending on it..
    -
    -// @baseUrl
    -Specify the base directory to resolve non-relative module names..
    -
    -// @charset
    -No longer supported. In early versions, manually set the text encoding for reading files..
    -
    -// @checkJs
    -Enable error reporting in type-checked JavaScript files..
    -
    -// @composite
    -Enable constraints that allow a TypeScript project to be used with project references..
    -
    -// @declaration
    -Generate .d.ts files from TypeScript and JavaScript files in your project..
    -
    -// @declarationDir
    -Specify the output directory for generated declaration files..
    -
    -// @declarationMap
    -Create sourcemaps for d.ts files..
    -
    -// @diagnostics
    -Output compiler performance information after building..
    -
    -// @disableReferencedProjectLoad
    -Reduce the number of projects loaded automatically by TypeScript..
    -
    -// @disableSizeLimit
    -Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
    -
    -// @disableSolutionSearching
    -Opt a project out of multi-project reference checking when editing..
    -
    -// @disableSourceOfProjectReferenceRedirect
    -Disable preferring source files instead of declaration files when referencing composite projects.
    -
    -// @downlevelIteration
    -Emit more compliant, but verbose and less performant JavaScript for iteration..
    -
    -// @emitBOM
    -Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
    -
    -// @emitDeclarationOnly
    -Only output d.ts files and not JavaScript files..
    -
    -// @emitDecoratorMetadata
    -Emit design-type metadata for decorated declarations in source files..
    -
    -// @esModuleInterop
    -Emit additional JavaScript to ease support for importing CommonJS modules. This enables \`allowSyntheticDefaultImports\` for type compatibility..
    -
    -// @exactOptionalPropertyTypes
    -Interpret optional property types as written, rather than adding 'undefined'..
    -
    -// @experimentalDecorators
    -Enable experimental support for TC39 stage 2 draft decorators..
    -
    -// @explainFiles
    -Print files read during the compilation including why it was included..
    -
    -// @extendedDiagnostics
    -Output more detailed compiler performance information after building..
    -
    -// @forceConsistentCasingInFileNames
    -Ensure that casing is correct in imports..
    -
    -// @generateCpuProfile
    -Emit a v8 CPU profile of the compiler run for debugging..
    -
    -// @importHelpers
    -Allow importing helper functions from tslib once per project, instead of including them per-file..
    -
    -// @importsNotUsedAsValues
    -Specify emit/checking behavior for imports that are only used for types.
    -
    -// @incremental
    -Enable incremental compilation.
    -
    -// @inlineSourceMap
    -Include sourcemap files inside the emitted JavaScript..
    -
    -// @inlineSources
    -Include source code in the sourcemaps inside the emitted JavaScript..
    -
    -// @isolatedModules
    -Ensure that each file can be safely transpiled without relying on other imports..
    -
    -// @jsx
    -Specify what JSX code is generated..
    -
    -// @jsxFactory
    -Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
    -
    -// @jsxFragmentFactory
    -Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
    -
    -// @jsxImportSource
    -Specify module specifier used to import the JSX factory functions when using \`jsx: react-jsx*\`.\`.
    -
    -// @keyofStringsOnly
    -Make keyof only return strings instead of string, numbers or symbols. Legacy option..
    -
    -// @lib
    -Specify a set of bundled library declaration files that describe the target runtime environment..
    -
    -// @listEmittedFiles
    -Print the names of emitted files after a compilation..
    -
    -// @listFiles
    -Print all of the files read during the compilation..
    -
    -// @mapRoot
    -Specify the location where debugger should locate map files instead of generated locations..
    -
    -// @maxNodeModuleJsDepth
    -Specify the maximum folder depth used for checking JavaScript files from \`node_modules\`. Only applicable with \`allowJs\`..
    -
    -// @module
    -Specify what module code is generated..
    -
    -// @moduleResolution
    -Specify how TypeScript looks up a file from a given module specifier..
    -
    -// @newLine
    -Set the newline character for emitting files..
    -
    -// @noEmit
    -Disable emitting file from a compilation..
    -
    -// @noEmitHelpers
    -Disable generating custom helper functions like \`__extends\` in compiled output..
    -
    -// @noEmitOnError
    -Disable emitting files if any type checking errors are reported..
    -
    -// @noErrorTruncation
    -Disable truncating types in error messages..
    -
    -// @noFallthroughCasesInSwitch
    -Enable error reporting for fallthrough cases in switch statements..
    -
    -// @noImplicitAny
    -Enable error reporting for expressions and declarations with an implied \`any\` type...
    -
    -// @noImplicitOverride
    -Add \`undefined\` to a type when accessed using an index..
    -
    -// @noImplicitReturns
    -Enable error reporting for codepaths that do not explicitly return in a function..
    -
    -// @noImplicitThis
    -Enable error reporting when \`this\` is given the type \`any\`..
    -
    -// @noImplicitUseStrict
    -Disable adding 'use strict' directives in emitted JavaScript files..
    -
    -// @noLib
    -Disable including any library files, including the default lib.d.ts..
    -
    -// @noPropertyAccessFromIndexSignature
    -Enforces using indexed accessors for keys declared using an indexed type.
    -
    -// @noResolve
    -Disallow \`import\`s, \`require\`s or \`\`s from expanding the number of files TypeScript should add to a project..
    -
    -// @noStrictGenericChecks
    -Disable strict checking of generic signatures in function types..
    -
    -// @noUncheckedIndexedAccess
    -Include 'undefined' in index signature results.
    -
    -// @noUnusedLocals
    -Enable error reporting when a local variables aren't read..
    -
    -// @noUnusedParameters
    -Raise an error when a function parameter isn't read.
    -
    -// @out
    -Deprecated setting. Use \`outFile\` instead..
    -
    -// @outDir
    -Specify an output folder for all emitted files..
    -
    -// @outFile
    -Specify a file that bundles all outputs into one JavaScript file. If \`declaration\` is true, also designates a file that bundles all .d.ts output..
    -
    -// @paths
    -Specify a set of entries that re-map imports to additional lookup locations..
    -
    -// @plugins
    -List of language service plugins..
    -
    -// @preserveConstEnums
    -Disable erasing \`const enum\` declarations in generated code..
    -
    -// @preserveSymlinks
    -Disable resolving symlinks to their realpath. This correlates to the same flag in node..
    -
    -// @preserveWatchOutput
    -Disable wiping the console in watch mode.
    -
    -// @pretty
    -Enable color and formatting in output to make compiler errors easier to read.
    -
    -// @reactNamespace
    -Specify the object invoked for \`createElement\`. This only applies when targeting \`react\` JSX emit..
    -
    -// @removeComments
    -Disable emitting comments..
    -
    -// @resolveJsonModule
    -Enable importing .json files.
    -
    -// @rootDir
    -Specify the root folder within your source files..
    -
    -// @rootDirs
    -Allow multiple folders to be treated as one when resolving modules..
    -
    -// @skipDefaultLibCheck
    -Skip type checking .d.ts files that are included with TypeScript..
    -
    -// @skipLibCheck
    -Skip type checking all .d.ts files..
    -
    -// @sourceMap
    -Create source map files for emitted JavaScript files..
    -
    -// @sourceRoot
    -Specify the root path for debuggers to find the reference source code..
    -
    -// @strict
    -Enable all strict type-checking options..
    -
    -// @strictBindCallApply
    -Check that the arguments for \`bind\`, \`call\`, and \`apply\` methods match the original function..
    -
    -// @strictFunctionTypes
    -When assigning functions, check to ensure parameters and the return values are subtype-compatible..
    -
    -// @strictNullChecks
    -When type checking, take into account \`null\` and \`undefined\`..
    -
    -// @strictPropertyInitialization
    -Check for class properties that are declared but not set in the constructor..
    -
    -// @stripInternal
    -Disable emitting declarations that have \`@internal\` in their JSDoc comments..
    -
    -// @suppressExcessPropertyErrors
    -Disable reporting of excess property errors during the creation of object literals..
    -
    -// @suppressImplicitAnyIndexErrors
    -Suppress \`noImplicitAny\` errors when indexing objects that lack index signatures..
    -
    -// @target
    -Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
    -
    -// @traceResolution
    -Log paths used during the \`moduleResolution\` process..
    -
    -// @tsBuildInfoFile
    -Specify the folder for .tsbuildinfo incremental compilation files..
    -
    -// @typeRoots
    -Specify multiple folders that act like \`./node_modules/@types\`..
    -
    -// @types
    -Specify type package names to be included without being referenced in a source file..
    -
    -// @useDefineForClassFields
    -Emit ECMAScript-standard-compliant class fields..
    -
    -// @useUnknownInCatchVariables
    -Type catch clause variables as 'unknown' instead of 'any'..
    `,1);function b(u,m,d,f,h,B){const n=a;return e(),p("div",null,[t,r(n,{readTime:"7",words:"1.1k"}),y])}const k=l(i,[["render",b]]);export{v as __pageData,k as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.a683705b.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.a683705b.lean.js deleted file mode 100644 index 24cc3543..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_config_flags.md.a683705b.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o as e,c as p,H as r,k as s,a as o,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Compiler Flags","description":"","frontmatter":{"title":"Compiler Flags"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/config/flags.md","filePath":"application/vitepress-plugin-shiki-twoslash/config/flags.md","lastUpdated":1695377563000}'),i={name:"application/vitepress-plugin-shiki-twoslash/config/flags.md"},t=s("h1",{id:"compiler-flags",tabindex:"-1"},[o("Compiler Flags "),s("a",{class:"header-anchor",href:"#compiler-flags","aria-label":'Permalink to "Compiler Flags"'},"​")],-1),y=c("",1);function b(u,m,d,f,h,B){const n=a;return e(),p("div",null,[t,r(n,{readTime:"7",words:"1.1k"}),y])}const k=l(i,[["render",b]]);export{v as __pageData,k as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.42f9e642.js b/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.42f9e642.js deleted file mode 100644 index 007eefd7..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.42f9e642.js +++ /dev/null @@ -1,83 +0,0 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o,c as p,H as t,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Config","description":"You can configure Twoslash to change code example output.","frontmatter":{"description":"You can configure Twoslash to change code example output.","title":"Config"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/config/reference.md","filePath":"application/vitepress-plugin-shiki-twoslash/config/reference.md","lastUpdated":1695377563000}'),r={name:"application/vitepress-plugin-shiki-twoslash/config/reference.md"},i=s("h1",{id:"config",tabindex:"-1"},[a("Config "),s("a",{class:"header-anchor",href:"#config","aria-label":'Permalink to "Config"'},"​")],-1),d=s("h2",{id:"overview",tabindex:"-1"},[a("Overview "),s("a",{class:"header-anchor",href:"#overview","aria-label":'Permalink to "Overview"'},"​")],-1),y=s("p",null,[a("You can configure VitePress Twoslash using the "),s("code",null,"twoslash"),a(" property added to "),s("code",null,"defineConfig"),a(".")],-1),h=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#839496"}},", "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) type TwoslashConfigSettings = any -import TwoslashConfigSettings`},"TwoslashConfigSettings")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#839496"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.twoslash?: any"},"twoslash"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"// Your VitePress Twoslash options")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#657B83"}},", "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) type TwoslashConfigSettings = any -import TwoslashConfigSettings`},"TwoslashConfigSettings")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#657B83"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.twoslash?: any"},"twoslash"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"// Your VitePress Twoslash options")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),u=c(`

    INFO

    In addition to the below config options, VitePress Twoslash also supports all shiki HighlighterOptions and @typescript/twoslash TwoSlashOptions.

    Options

    addTryButton

    A way to turn on the try buttons seen on the TS website.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            addTryButton: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            addTryButton: true, 
    -        },
    -    })
    -)

    alwayRaiseForTwoslashExceptions

    Instead of showing twoslash exceptions inline, throw the entire process like it will on CI.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            alwayRaiseForTwoslashExceptions: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            alwayRaiseForTwoslashExceptions: true, 
    -        },
    -    })
    -)

    disableImplicitReactImport

    A way to disable implicit React imports on tsx/jsx language codeblocks

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            disableImplicitReactImport: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            disableImplicitReactImport: true, 
    -        },
    -    })
    -)

    includeJSDocInHover

    Include JSDoc comments in the hovers.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            includeJSDocInHover: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            includeJSDocInHover: true, 
    -        },
    -    })
    -)

    ignoreCodeblocksWithCodefenceMeta

    Ignore transforming certain code blocks.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            ignoreCodeblocksWithCodefenceMeta: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            ignoreCodeblocksWithCodefenceMeta: true, 
    -        },
    -    })
    -)

    wrapFragments

    A way to add a div wrapper for multi-theme outputs.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            wrapFragments: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            wrapFragments: true, 
    -        },
    -    })
    -)
    `,26);function f(g,m,b,B,w,v){const n=l;return o(),p("div",null,[i,t(n,{readTime:"1",words:"248"}),d,y,h,u])}const x=e(r,[["render",f]]);export{k as __pageData,x as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.42f9e642.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.42f9e642.lean.js deleted file mode 100644 index d92fa00c..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.42f9e642.lean.js +++ /dev/null @@ -1,11 +0,0 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o,c as p,H as t,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Config","description":"You can configure Twoslash to change code example output.","frontmatter":{"description":"You can configure Twoslash to change code example output.","title":"Config"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/config/reference.md","filePath":"application/vitepress-plugin-shiki-twoslash/config/reference.md","lastUpdated":1695377563000}'),r={name:"application/vitepress-plugin-shiki-twoslash/config/reference.md"},i=s("h1",{id:"config",tabindex:"-1"},[a("Config "),s("a",{class:"header-anchor",href:"#config","aria-label":'Permalink to "Config"'},"​")],-1),d=s("h2",{id:"overview",tabindex:"-1"},[a("Overview "),s("a",{class:"header-anchor",href:"#overview","aria-label":'Permalink to "Overview"'},"​")],-1),y=s("p",null,[a("You can configure VitePress Twoslash using the "),s("code",null,"twoslash"),a(" property added to "),s("code",null,"defineConfig"),a(".")],-1),h=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#839496"}},", "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) type TwoslashConfigSettings = any -import TwoslashConfigSettings`},"TwoslashConfigSettings")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#839496"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.twoslash?: any"},"twoslash"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"// Your VitePress Twoslash options")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#657B83"}},", "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) type TwoslashConfigSettings = any -import TwoslashConfigSettings`},"TwoslashConfigSettings")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#657B83"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.twoslash?: any"},"twoslash"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"// Your VitePress Twoslash options")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),u=c("",26);function f(g,m,b,B,w,v){const n=l;return o(),p("div",null,[i,t(n,{readTime:"1",words:"248"}),d,y,h,u])}const x=e(r,[["render",f]]);export{k as __pageData,x as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.e7b86a5d.js b/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.e7b86a5d.js new file mode 100644 index 00000000..8b250b06 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.e7b86a5d.js @@ -0,0 +1,83 @@ +import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o,c as p,H as t,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Config","description":"You can configure Twoslash to change code example output.","frontmatter":{"description":"You can configure Twoslash to change code example output.","title":"Config"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/config/reference.md","filePath":"application/vitepress-plugin-shiki-twoslash/config/reference.md","lastUpdated":1699051935000}'),i={name:"application/vitepress-plugin-shiki-twoslash/config/reference.md"},r=s("h1",{id:"config",tabindex:"-1"},[a("Config "),s("a",{class:"header-anchor",href:"#config","aria-label":'Permalink to "Config"'},"​")],-1),d=s("h2",{id:"overview",tabindex:"-1"},[a("Overview "),s("a",{class:"header-anchor",href:"#overview","aria-label":'Permalink to "Overview"'},"​")],-1),y=s("p",null,[a("You can configure VitePress Twoslash using the "),s("code",null,"twoslash"),a(" property added to "),s("code",null,"defineConfig"),a(".")],-1),h=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[a(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),a(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[a(" { "),s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash"),a(", "),s("data-lsp",{lsp:`(alias) type TwoslashConfigSettings = any +import TwoslashConfigSettings`},"TwoslashConfigSettings"),a(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#F69D50"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#F69D50"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"(property) UserConfig.twoslash?: any"},"twoslash"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your VitePress Twoslash options")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }"),s("span",{style:{color:"#F69D50"}},",")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}},")")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[a(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),a(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[a(" { "),s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash"),a(", "),s("data-lsp",{lsp:`(alias) type TwoslashConfigSettings = any +import TwoslashConfigSettings`},"TwoslashConfigSettings"),a(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#24292E"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.twoslash?: any"},"twoslash"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// Your VitePress Twoslash options")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),u=c(`

    INFO

    In addition to the below config options, VitePress Twoslash also supports all shiki HighlighterOptions and @typescript/twoslash TwoSlashOptions.

    Options

    addTryButton

    A way to turn on the try buttons seen on the TS website.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            addTryButton: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            addTryButton: true, 
    +        },
    +    })
    +)

    alwayRaiseForTwoslashExceptions

    Instead of showing twoslash exceptions inline, throw the entire process like it will on CI.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            alwayRaiseForTwoslashExceptions: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            alwayRaiseForTwoslashExceptions: true, 
    +        },
    +    })
    +)

    disableImplicitReactImport

    A way to disable implicit React imports on tsx/jsx language codeblocks

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            disableImplicitReactImport: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            disableImplicitReactImport: true, 
    +        },
    +    })
    +)

    includeJSDocInHover

    Include JSDoc comments in the hovers.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            includeJSDocInHover: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            includeJSDocInHover: true, 
    +        },
    +    })
    +)

    ignoreCodeblocksWithCodefenceMeta

    Ignore transforming certain code blocks.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            ignoreCodeblocksWithCodefenceMeta: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            ignoreCodeblocksWithCodefenceMeta: true, 
    +        },
    +    })
    +)

    wrapFragments

    A way to add a div wrapper for multi-theme outputs.

    • Type: boolean
    • Default: false
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            wrapFragments: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            wrapFragments: true, 
    +        },
    +    })
    +)
    `,26);function f(g,m,b,D,C,F){const n=l;return o(),p("div",null,[r,t(n,{readTime:"1",words:"248"}),d,y,h,u])}const T=e(i,[["render",f]]);export{E as __pageData,T as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.e7b86a5d.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.e7b86a5d.lean.js new file mode 100644 index 00000000..2beb0cf3 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_config_reference.md.e7b86a5d.lean.js @@ -0,0 +1,11 @@ +import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o,c as p,H as t,k as s,a,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Config","description":"You can configure Twoslash to change code example output.","frontmatter":{"description":"You can configure Twoslash to change code example output.","title":"Config"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/config/reference.md","filePath":"application/vitepress-plugin-shiki-twoslash/config/reference.md","lastUpdated":1699051935000}'),i={name:"application/vitepress-plugin-shiki-twoslash/config/reference.md"},r=s("h1",{id:"config",tabindex:"-1"},[a("Config "),s("a",{class:"header-anchor",href:"#config","aria-label":'Permalink to "Config"'},"​")],-1),d=s("h2",{id:"overview",tabindex:"-1"},[a("Overview "),s("a",{class:"header-anchor",href:"#overview","aria-label":'Permalink to "Overview"'},"​")],-1),y=s("p",null,[a("You can configure VitePress Twoslash using the "),s("code",null,"twoslash"),a(" property added to "),s("code",null,"defineConfig"),a(".")],-1),h=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[a(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),a(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[a(" { "),s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash"),a(", "),s("data-lsp",{lsp:`(alias) type TwoslashConfigSettings = any +import TwoslashConfigSettings`},"TwoslashConfigSettings"),a(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#F69D50"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#F69D50"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"(property) UserConfig.twoslash?: any"},"twoslash"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your VitePress Twoslash options")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }"),s("span",{style:{color:"#F69D50"}},",")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}},")")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[a(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),a(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[a(" { "),s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash"),a(", "),s("data-lsp",{lsp:`(alias) type TwoslashConfigSettings = any +import TwoslashConfigSettings`},"TwoslashConfigSettings"),a(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#24292E"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.twoslash?: any"},"twoslash"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// Your VitePress Twoslash options")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),u=c("",26);function f(g,m,b,D,C,F){const n=l;return o(),p("div",null,[r,t(n,{readTime:"1",words:"248"}),d,y,h,u])}const T=e(i,[["render",f]]);export{E as __pageData,T as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.287ab776.js b/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.287ab776.js new file mode 100644 index 00000000..c99441f7 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.287ab776.js @@ -0,0 +1,85 @@ +import{_ as p}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as e,c as r,H as c,k as s,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const u=JSON.parse('{"title":"Using a Custom Theme","description":"Customize the Twoslash interface to match your theme.","frontmatter":{"description":"Customize the Twoslash interface to match your theme.","title":"Using a Custom Theme"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md","filePath":"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md","lastUpdated":1699051935000}'),t={name:"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md"},y=s("h1",{id:"using-a-custom-theme",tabindex:"-1"},[a("Using a Custom Theme "),s("a",{class:"header-anchor",href:"#using-a-custom-theme","aria-label":'Permalink to "Using a Custom Theme"'},"​")],-1),i=n(`

    Twoslash uses your markdown.theme for syntax highlighting, but there are a few other things you can do to customize the look and feel of your code examples — particulary the generated Twoslash interface.

    CSS Variables

    The following CSS variables (and their defaults) are available to style Twoslash interface:

    css
    :root {
    +    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
    +
    +    --vp-twoslash-c-brand: var(--vp-c-brand);
    +
    +    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
    +
    +    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    +    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    +    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    +    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    +    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
    +
    +    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    +    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    +    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    +    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
    +
    +    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    +    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    +    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    +}
    :root {
    +    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
    +
    +    --vp-twoslash-c-brand: var(--vp-c-brand);
    +
    +    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
    +
    +    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    +    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    +    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    +    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    +    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
    +
    +    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    +    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    +    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    +    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
    +
    +    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    +    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    +    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    +}

    Dark/Light Theme

    If you pass a responsive theme to markdown.theme, you probably also want to hide/show the correct theme based on the user's settings.

    `,6),C=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#F69D50"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"(property) UserConfig.markdown?: MarkdownOptions | undefined"},"markdown"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[a(" "),s("data-lsp",{lsp:"(property) MarkdownOptions.theme?: any"},"theme"),a(": { "),s("data-lsp",{lsp:"(property) dark: string"},"dark"),a(": ")]),s("span",{style:{color:"#96D0FF"}},"'vitesse-dark'"),s("span",{style:{color:"#ADBAC7"}},[a(", "),s("data-lsp",{lsp:"(property) light: string"},"light"),a(": ")]),s("span",{style:{color:"#96D0FF"}},"'vitesse-light'"),s("span",{style:{color:"#ADBAC7"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }"),s("span",{style:{color:"#F69D50"}},",")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}},"})")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.markdown?: MarkdownOptions | undefined"},"markdown"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[a(" "),s("data-lsp",{lsp:"(property) MarkdownOptions.theme?: any"},"theme"),a(": { "),s("data-lsp",{lsp:"(property) dark: string"},"dark"),a(": ")]),s("span",{style:{color:"#032F62"}},"'vitesse-dark'"),s("span",{style:{color:"#24292E"}},[a(", "),s("data-lsp",{lsp:"(property) light: string"},"light"),a(": ")]),s("span",{style:{color:"#032F62"}},"'vitesse-light'"),s("span",{style:{color:"#24292E"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),A=n(`

    You can do this with the following CSS:

    css
    /*
    + * Hide block based on theme
    + * \`[class*='-dark']\` matches \`'vitesse-dark'\`
    + * \`[class*='-light']\` matches \`'vitesse-light'\`
    + */
    +html:not(.dark) pre.shiki[class*='-dark'] {
    +    display: none;
    +}
    +html:not(.dark) pre.shiki[class*='-light'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-dark'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-light'] {
    +    display: none;
    +}
    /*
    + * Hide block based on theme
    + * \`[class*='-dark']\` matches \`'vitesse-dark'\`
    + * \`[class*='-light']\` matches \`'vitesse-light'\`
    + */
    +html:not(.dark) pre.shiki[class*='-dark'] {
    +    display: none;
    +}
    +html:not(.dark) pre.shiki[class*='-light'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-dark'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-light'] {
    +    display: none;
    +}
    `,2);function d(D,h,v,F,B,m){const l=p;return e(),r("div",null,[y,c(l,{readTime:"2",words:"362"}),i,C,A])}const f=o(t,[["render",d]]);export{u as __pageData,f as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.287ab776.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.287ab776.lean.js new file mode 100644 index 00000000..88f32da6 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.287ab776.lean.js @@ -0,0 +1,3 @@ +import{_ as p}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as e,c as r,H as c,k as s,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const u=JSON.parse('{"title":"Using a Custom Theme","description":"Customize the Twoslash interface to match your theme.","frontmatter":{"description":"Customize the Twoslash interface to match your theme.","title":"Using a Custom Theme"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md","filePath":"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md","lastUpdated":1699051935000}'),t={name:"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md"},y=s("h1",{id:"using-a-custom-theme",tabindex:"-1"},[a("Using a Custom Theme "),s("a",{class:"header-anchor",href:"#using-a-custom-theme","aria-label":'Permalink to "Using a Custom Theme"'},"​")],-1),i=n("",6),C=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#F69D50"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"(property) UserConfig.markdown?: MarkdownOptions | undefined"},"markdown"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[a(" "),s("data-lsp",{lsp:"(property) MarkdownOptions.theme?: any"},"theme"),a(": { "),s("data-lsp",{lsp:"(property) dark: string"},"dark"),a(": ")]),s("span",{style:{color:"#96D0FF"}},"'vitesse-dark'"),s("span",{style:{color:"#ADBAC7"}},[a(", "),s("data-lsp",{lsp:"(property) light: string"},"light"),a(": ")]),s("span",{style:{color:"#96D0FF"}},"'vitesse-light'"),s("span",{style:{color:"#ADBAC7"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }"),s("span",{style:{color:"#F69D50"}},",")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}},"})")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.markdown?: MarkdownOptions | undefined"},"markdown"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[a(" "),s("data-lsp",{lsp:"(property) MarkdownOptions.theme?: any"},"theme"),a(": { "),s("data-lsp",{lsp:"(property) dark: string"},"dark"),a(": ")]),s("span",{style:{color:"#032F62"}},"'vitesse-dark'"),s("span",{style:{color:"#24292E"}},[a(", "),s("data-lsp",{lsp:"(property) light: string"},"light"),a(": ")]),s("span",{style:{color:"#032F62"}},"'vitesse-light'"),s("span",{style:{color:"#24292E"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),A=n("",2);function d(D,h,v,F,B,m){const l=p;return e(),r("div",null,[y,c(l,{readTime:"2",words:"362"}),i,C,A])}const f=o(t,[["render",d]]);export{u as __pageData,f as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.58ed95fc.js b/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.58ed95fc.js deleted file mode 100644 index 10c741e4..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.58ed95fc.js +++ /dev/null @@ -1,85 +0,0 @@ -import{_ as p}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o,c as r,H as t,k as s,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const D=JSON.parse('{"title":"Using a Custom Theme","description":"Customize the Twoslash interface to match your theme.","frontmatter":{"description":"Customize the Twoslash interface to match your theme.","title":"Using a Custom Theme"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md","filePath":"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md","lastUpdated":1695377563000}'),c={name:"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md"},i=s("h1",{id:"using-a-custom-theme",tabindex:"-1"},[a("Using a Custom Theme "),s("a",{class:"header-anchor",href:"#using-a-custom-theme","aria-label":'Permalink to "Using a Custom Theme"'},"​")],-1),y=n(`

    Twoslash uses your markdown.theme for syntax highlighting, but there are a few other things you can do to customize the look and feel of your code examples — particulary the generated Twoslash interface.

    CSS Variables

    The following CSS variables (and their defaults) are available to style Twoslash interface:

    css
    :root {
    -    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
    -
    -    --vp-twoslash-c-brand: var(--vp-c-brand);
    -
    -    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
    -
    -    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    -    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    -    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    -    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    -    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
    -
    -    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    -    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    -    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    -    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
    -
    -    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    -    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    -    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    -}
    :root {
    -    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
    -
    -    --vp-twoslash-c-brand: var(--vp-c-brand);
    -
    -    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
    -
    -    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    -    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    -    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    -    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    -    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
    -
    -    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    -    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    -    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    -    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
    -
    -    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    -    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    -    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    -}

    Dark/Light Theme

    If you pass a responsive theme to markdown.theme, you probably also want to hide/show the correct theme based on the user's settings.

    `,6),d=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.markdown?: MarkdownOptions | undefined"},"markdown"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},[a(" "),s("data-lsp",{lsp:"(property) MarkdownOptions.theme?: any"},"theme"),a(": { "),s("data-lsp",{lsp:"(property) dark: string"},"dark"),a(": ")]),s("span",{style:{color:"#2AA198"}},"'vitesse-dark'"),s("span",{style:{color:"#839496"}},[a(", "),s("data-lsp",{lsp:"(property) light: string"},"light"),a(": ")]),s("span",{style:{color:"#2AA198"}},"'vitesse-light'"),s("span",{style:{color:"#839496"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"})")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.markdown?: MarkdownOptions | undefined"},"markdown"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},[a(" "),s("data-lsp",{lsp:"(property) MarkdownOptions.theme?: any"},"theme"),a(": { "),s("data-lsp",{lsp:"(property) dark: string"},"dark"),a(": ")]),s("span",{style:{color:"#2AA198"}},"'vitesse-dark'"),s("span",{style:{color:"#657B83"}},[a(", "),s("data-lsp",{lsp:"(property) light: string"},"light"),a(": ")]),s("span",{style:{color:"#2AA198"}},"'vitesse-light'"),s("span",{style:{color:"#657B83"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),h=n(`

    You can do this with the following CSS:

    css
    /*
    - * Hide block based on theme
    - * \`[class*='-dark']\` matches \`'vitesse-dark'\`
    - * \`[class*='-light']\` matches \`'vitesse-light'\`
    - */
    -html:not(.dark) pre.shiki[class*='-dark'] {
    -    display: none;
    -}
    -html:not(.dark) pre.shiki[class*='-light'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-dark'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-light'] {
    -    display: none;
    -}
    /*
    - * Hide block based on theme
    - * \`[class*='-dark']\` matches \`'vitesse-dark'\`
    - * \`[class*='-light']\` matches \`'vitesse-light'\`
    - */
    -html:not(.dark) pre.shiki[class*='-dark'] {
    -    display: none;
    -}
    -html:not(.dark) pre.shiki[class*='-light'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-dark'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-light'] {
    -    display: none;
    -}
    `,2);function v(m,g,b,B,u,A){const l=p;return o(),r("div",null,[i,t(l,{readTime:"2",words:"362"}),y,d,h])}const _=e(c,[["render",v]]);export{D as __pageData,_ as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.58ed95fc.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.58ed95fc.lean.js deleted file mode 100644 index ae279939..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md.58ed95fc.lean.js +++ /dev/null @@ -1,3 +0,0 @@ -import{_ as p}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o,c as r,H as t,k as s,a,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const D=JSON.parse('{"title":"Using a Custom Theme","description":"Customize the Twoslash interface to match your theme.","frontmatter":{"description":"Customize the Twoslash interface to match your theme.","title":"Using a Custom Theme"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md","filePath":"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md","lastUpdated":1695377563000}'),c={name:"application/vitepress-plugin-shiki-twoslash/guide/custom-theme.md"},i=s("h1",{id:"using-a-custom-theme",tabindex:"-1"},[a("Using a Custom Theme "),s("a",{class:"header-anchor",href:"#using-a-custom-theme","aria-label":'Permalink to "Using a Custom Theme"'},"​")],-1),y=n("",6),d=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.markdown?: MarkdownOptions | undefined"},"markdown"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},[a(" "),s("data-lsp",{lsp:"(property) MarkdownOptions.theme?: any"},"theme"),a(": { "),s("data-lsp",{lsp:"(property) dark: string"},"dark"),a(": ")]),s("span",{style:{color:"#2AA198"}},"'vitesse-dark'"),s("span",{style:{color:"#839496"}},[a(", "),s("data-lsp",{lsp:"(property) light: string"},"light"),a(": ")]),s("span",{style:{color:"#2AA198"}},"'vitesse-light'"),s("span",{style:{color:"#839496"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"})")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},[a(" "),s("data-lsp",{lsp:"(property) UserConfig.markdown?: MarkdownOptions | undefined"},"markdown"),a(": {")])]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},[a(" "),s("data-lsp",{lsp:"(property) MarkdownOptions.theme?: any"},"theme"),a(": { "),s("data-lsp",{lsp:"(property) dark: string"},"dark"),a(": ")]),s("span",{style:{color:"#2AA198"}},"'vitesse-dark'"),s("span",{style:{color:"#657B83"}},[a(", "),s("data-lsp",{lsp:"(property) light: string"},"light"),a(": ")]),s("span",{style:{color:"#2AA198"}},"'vitesse-light'"),s("span",{style:{color:"#657B83"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," },")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),h=n("",2);function v(m,g,b,B,u,A){const l=p;return o(),r("div",null,[i,t(l,{readTime:"2",words:"362"}),y,d,h])}const _=e(c,[["render",v]]);export{D as __pageData,_ as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.6731e737.js b/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.6731e737.js deleted file mode 100644 index 8b9be8db..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.6731e737.js +++ /dev/null @@ -1,7 +0,0 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as r,k as s,a as e,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const A=JSON.parse('{"title":"Markdown Extensions","description":"","frontmatter":{"title":"Markdown Extensions"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md","filePath":"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md","lastUpdated":1695377563000}'),p={name:"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md"},c=s("h1",{id:"markdown-extensions",tabindex:"-1"},[e("Markdown Extensions "),s("a",{class:"header-anchor",href:"#markdown-extensions","aria-label":'Permalink to "Markdown Extensions"'},"​")],-1),d=s("h2",{id:"code-groups",tabindex:"-1"},[e("Code Groups "),s("a",{class:"header-anchor",href:"#code-groups","aria-label":'Permalink to "Code Groups"'},"​")],-1),h=s("p",null,[s("a",{href:"https://vitepress.dev/guide/markdown#code-groups",target:"_blank",rel:"noreferrer"},"Code Groups"),e(" and Twoslash "),s("a",{href:"/api/multi-file"},"multi-file"),e(" support.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-kgThu",id:"tab-tV4Z_sQ",checked:"checked"}),s("label",{for:"tab-tV4Z_sQ"},"index.ts"),s("input",{type:"radio",name:"group-kgThu",id:"tab-ESdMbif"}),s("label",{for:"tab-ESdMbif"},"name.ts")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const name: "twoslash" -import name`},"name")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'./name'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#839496"}},[e("("),s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}},") {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"`Hello, ${"),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#2AA198"}},"}!`"),s("span",{style:{color:"#839496"}},")")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const name: "twoslash" -import name`,style:{"border-bottom":"solid 2px lightgrey"}},"name")]),s("span",{style:{color:"#839496"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),e(`(alias) const name: "twoslash" -import name`)])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const name: "twoslash" -import name`},"name")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'./name'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#657B83"}},[e("("),s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}},") {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"`Hello, ${"),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#2AA198"}},"}!`"),s("span",{style:{color:"#657B83"}},")")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const name: "twoslash" -import name`,style:{"border-bottom":"solid 2px lightgrey"}},"name")]),s("span",{style:{color:"#657B83"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),e(`(alias) const name: "twoslash" -import name`)])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br")])]),s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const name: "twoslash"'},"name")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'twoslash'")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const name: "twoslash"'},"name")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'twoslash'")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])])])],-1),y=i('

    Unsupported Extensions

    Since VitePress Twoslash uses it's own Shiki highlighter, the following syntax highlighting extensions are not currently compatible.

    If you are interested in adding support, please start a new GitHub Discussion.

    ',4);function u(g,v,k,f,b,_){const o=l;return n(),t("div",null,[c,r(o,{readTime:"1",words:"181"}),d,h,m,y])}const D=a(p,[["render",u]]);export{A as __pageData,D as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.6731e737.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.6731e737.lean.js deleted file mode 100644 index 7f597120..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.6731e737.lean.js +++ /dev/null @@ -1,7 +0,0 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as a,o as n,c as t,H as r,k as s,a as e,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const A=JSON.parse('{"title":"Markdown Extensions","description":"","frontmatter":{"title":"Markdown Extensions"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md","filePath":"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md","lastUpdated":1695377563000}'),p={name:"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md"},c=s("h1",{id:"markdown-extensions",tabindex:"-1"},[e("Markdown Extensions "),s("a",{class:"header-anchor",href:"#markdown-extensions","aria-label":'Permalink to "Markdown Extensions"'},"​")],-1),d=s("h2",{id:"code-groups",tabindex:"-1"},[e("Code Groups "),s("a",{class:"header-anchor",href:"#code-groups","aria-label":'Permalink to "Code Groups"'},"​")],-1),h=s("p",null,[s("a",{href:"https://vitepress.dev/guide/markdown#code-groups",target:"_blank",rel:"noreferrer"},"Code Groups"),e(" and Twoslash "),s("a",{href:"/api/multi-file"},"multi-file"),e(" support.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-kgThu",id:"tab-tV4Z_sQ",checked:"checked"}),s("label",{for:"tab-tV4Z_sQ"},"index.ts"),s("input",{type:"radio",name:"group-kgThu",id:"tab-ESdMbif"}),s("label",{for:"tab-ESdMbif"},"name.ts")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const name: "twoslash" -import name`},"name")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'./name'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"function"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#839496"}},[e("("),s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#839496"}},") {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#839496"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#2AA198"}},"`Hello, ${"),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#2AA198"}},"}!`"),s("span",{style:{color:"#839496"}},")")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#839496"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const name: "twoslash" -import name`,style:{"border-bottom":"solid 2px lightgrey"}},"name")]),s("span",{style:{color:"#839496"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),e(`(alias) const name: "twoslash" -import name`)])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const name: "twoslash" -import name`},"name")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'./name'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"function"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#657B83"}},[e("("),s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string"),s("span",{style:{color:"#657B83"}},") {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"var console: Console"},"console")]),s("span",{style:{color:"#657B83"}},"."),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#2AA198"}},"`Hello, ${"),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#2AA198"}},"}!`"),s("span",{style:{color:"#657B83"}},")")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"},[s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#657B83"}},"("),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const name: "twoslash" -import name`,style:{"border-bottom":"solid 2px lightgrey"}},"name")]),s("span",{style:{color:"#657B83"}},")")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),e(`(alias) const name: "twoslash" -import name`)])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br")])]),s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"const"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const name: "twoslash"'},"name")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'twoslash'")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"const"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:'const name: "twoslash"'},"name")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'twoslash'")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])])])],-1),y=i("",4);function u(g,v,k,f,b,_){const o=l;return n(),t("div",null,[c,r(o,{readTime:"1",words:"181"}),d,h,m,y])}const D=a(p,[["render",u]]);export{A as __pageData,D as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.a9cd6c63.js b/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.a9cd6c63.js new file mode 100644 index 00000000..d001eab2 --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.a9cd6c63.js @@ -0,0 +1,7 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o as n,c as t,H as r,k as s,a as e,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const D=JSON.parse('{"title":"Markdown Extensions","description":"","frontmatter":{"title":"Markdown Extensions"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md","filePath":"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md","lastUpdated":1699051935000}'),p={name:"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md"},c=s("h1",{id:"markdown-extensions",tabindex:"-1"},[e("Markdown Extensions "),s("a",{class:"header-anchor",href:"#markdown-extensions","aria-label":'Permalink to "Markdown Extensions"'},"​")],-1),d=s("h2",{id:"code-groups",tabindex:"-1"},[e("Code Groups "),s("a",{class:"header-anchor",href:"#code-groups","aria-label":'Permalink to "Code Groups"'},"​")],-1),h=s("p",null,[s("a",{href:"https://vitepress.dev/guide/markdown#code-groups",target:"_blank",rel:"noreferrer"},"Code Groups"),e(" and Twoslash "),s("a",{href:"/api/multi-file"},"multi-file"),e(" support.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-US2BG",id:"tab--8MRlLR",checked:"checked"}),s("label",{for:"tab--8MRlLR"},"index.ts"),s("input",{type:"radio",name:"group-US2BG",id:"tab-DJy2cAB"}),s("label",{for:"tab-DJy2cAB"},"name.ts")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[e(" { "),s("data-lsp",{lsp:`(alias) const name: "twoslash" +import name`},"name"),e(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'./name'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}},") {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[e(" "),s("data-lsp",{lsp:"var console: Console"},"console"),e(".")]),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"`Hello, ${"),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#96D0FF"}},"}!`"),s("span",{style:{color:"#ADBAC7"}},")")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#ADBAC7"}},[e("("),s("data-lsp",{lsp:`(alias) const name: "twoslash" +import name`,style:{"border-bottom":"solid 2px lightgrey"}},"name"),e(")")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),e(`(alias) const name: "twoslash" +import name`)])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[e(" { "),s("data-lsp",{lsp:`(alias) const name: "twoslash" +import name`},"name"),e(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'./name'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}},") {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[e(" "),s("data-lsp",{lsp:"var console: Console"},"console"),e(".")]),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"`Hello, ${"),s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#032F62"}},"}!`"),s("span",{style:{color:"#24292E"}},")")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"},[s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#24292E"}},[e("("),s("data-lsp",{lsp:`(alias) const name: "twoslash" +import name`,style:{"border-bottom":"solid 2px lightgrey"}},"name"),e(")")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),e(`(alias) const name: "twoslash" +import name`)])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br")])]),s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:'const name: "twoslash"'},"name")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'twoslash'")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:'const name: "twoslash"'},"name")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'twoslash'")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])])])],-1),u=i('

    Unsupported Extensions

    Since VitePress Twoslash uses it's own Shiki highlighter, the following syntax highlighting extensions are not currently compatible.

    If you are interested in adding support, please start a new GitHub Discussion.

    ',4);function y(g,v,k,f,b,C){const o=a;return n(),t("div",null,[c,r(o,{readTime:"1",words:"181"}),d,h,m,u])}const B=l(p,[["render",y]]);export{D as __pageData,B as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.a9cd6c63.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.a9cd6c63.lean.js new file mode 100644 index 00000000..08a3624c --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md.a9cd6c63.lean.js @@ -0,0 +1,7 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,o as n,c as t,H as r,k as s,a as e,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const D=JSON.parse('{"title":"Markdown Extensions","description":"","frontmatter":{"title":"Markdown Extensions"},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md","filePath":"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md","lastUpdated":1699051935000}'),p={name:"application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions.md"},c=s("h1",{id:"markdown-extensions",tabindex:"-1"},[e("Markdown Extensions "),s("a",{class:"header-anchor",href:"#markdown-extensions","aria-label":'Permalink to "Markdown Extensions"'},"​")],-1),d=s("h2",{id:"code-groups",tabindex:"-1"},[e("Code Groups "),s("a",{class:"header-anchor",href:"#code-groups","aria-label":'Permalink to "Code Groups"'},"​")],-1),h=s("p",null,[s("a",{href:"https://vitepress.dev/guide/markdown#code-groups",target:"_blank",rel:"noreferrer"},"Code Groups"),e(" and Twoslash "),s("a",{href:"/api/multi-file"},"multi-file"),e(" support.")],-1),m=s("div",{class:"vp-code-group vp-adaptive-theme"},[s("div",{class:"tabs"},[s("input",{type:"radio",name:"group-US2BG",id:"tab--8MRlLR",checked:"checked"}),s("label",{for:"tab--8MRlLR"},"index.ts"),s("input",{type:"radio",name:"group-US2BG",id:"tab-DJy2cAB"}),s("label",{for:"tab-DJy2cAB"},"name.ts")]),s("div",{class:"blocks"},[s("div",{class:"language-ts vp-adaptive-theme active line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[e(" { "),s("data-lsp",{lsp:`(alias) const name: "twoslash" +import name`},"name"),e(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'./name'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"function"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string"),s("span",{style:{color:"#ADBAC7"}},") {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},[e(" "),s("data-lsp",{lsp:"var console: Console"},"console"),e(".")]),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},"`Hello, ${"),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#96D0FF"}},"}!`"),s("span",{style:{color:"#ADBAC7"}},")")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"},[s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#ADBAC7"}},[e("("),s("data-lsp",{lsp:`(alias) const name: "twoslash" +import name`,style:{"border-bottom":"solid 2px lightgrey"}},"name"),e(")")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),e(`(alias) const name: "twoslash" +import name`)])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[e(" { "),s("data-lsp",{lsp:`(alias) const name: "twoslash" +import name`},"name"),e(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'./name'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"function"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string"),s("span",{style:{color:"#24292E"}},") {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[e(" "),s("data-lsp",{lsp:"var console: Console"},"console"),e(".")]),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(method) Console.log(...data: any[]): void"},"log")]),s("span",{style:{color:"#24292E"}},"("),s("span",{style:{color:"#032F62"}},"`Hello, ${"),s("span",{style:{color:"#24292E"}},[s("data-lsp",{lsp:"(parameter) name: string"},"name")]),s("span",{style:{color:"#032F62"}},"}!`"),s("span",{style:{color:"#24292E"}},")")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"},[s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"function hello(name: string): void"},"hello")]),s("span",{style:{color:"#24292E"}},[e("("),s("data-lsp",{lsp:`(alias) const name: "twoslash" +import name`,style:{"border-bottom":"solid 2px lightgrey"}},"name"),e(")")])]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),e(`(alias) const name: "twoslash" +import name`)])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br")])]),s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"const"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},[s("data-lsp",{lsp:'const name: "twoslash"'},"name")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'twoslash'")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"const"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},[s("data-lsp",{lsp:'const name: "twoslash"'},"name")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'twoslash'")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])])])],-1),u=i("",4);function y(g,v,k,f,b,C){const o=a;return n(),t("div",null,[c,r(o,{readTime:"1",words:"181"}),d,h,m,u])}const B=l(p,[["render",y]]);export{D as __pageData,B as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_index.md.7fc07d32.js b/assets/application_vitepress-plugin-shiki-twoslash_index.md.7fc07d32.js deleted file mode 100644 index c2ae4739..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_index.md.7fc07d32.js +++ /dev/null @@ -1,111 +0,0 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as p,c as t,H as r,k as s,a as l,Q as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const M=JSON.parse('{"title":"VitePress Twoslash: VitePress Plugin for Shiki Twoslash","titleTemplate":false,"description":"Static code examples for VitePress using Shiki Twoslash.","frontmatter":{"description":"Static code examples for VitePress using Shiki Twoslash.","title":"VitePress Twoslash: VitePress Plugin for Shiki Twoslash","titleTemplate":false,"keywords":["getting-started","intro"]},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/index.md","filePath":"application/vitepress-plugin-shiki-twoslash/index.md","lastUpdated":1695377563000}'),c={name:"application/vitepress-plugin-shiki-twoslash/index.md"},i=s("h1",{id:"andatoshiki-vitepress-plugin-shiki-twoslash",tabindex:"-1"},[l("@andatoshiki/vitepress-plugin-shiki-twoslash "),s("a",{class:"header-anchor",href:"#andatoshiki-vitepress-plugin-shiki-twoslash","aria-label":'Permalink to "@andatoshiki/vitepress-plugin-shiki-twoslash"'},"​")],-1),y=s("blockquote",null,[s("p",null,[l("Static code examples for "),s("a",{href:"https://vitepress.dev",target:"_blank",rel:"noreferrer"},"VitePress"),l(" using "),s("a",{href:"https://github.com/shikijs/twoslash",target:"_blank",rel:"noreferrer"},"Shiki Twoslash"),l(" — powered by the syntax engine of Visual Studio Code and the TypeScript compiler.")])],-1),d=s("h2",{id:"overview",tabindex:"-1"},[l("Overview "),s("a",{class:"header-anchor",href:"#overview","aria-label":'Permalink to "Overview"'},"​")],-1),u=s("p",null,"Try moving your cursor into the code block below:",-1),h=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#839496"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"> "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"-"),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}}," ["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"in"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"keyof"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"]"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#839496"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}},[l(),s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}},[l(),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type UnlockedAccount = { - id: string; - name: string; -}`},"UnlockedAccount")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#839496"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#839496"}},">")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#657B83"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"> "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"-"),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}}," ["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"in"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"keyof"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"]"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#657B83"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}},[l(),s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}},[l(),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type UnlockedAccount = { - id: string; - name: string; -}`},"UnlockedAccount")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#657B83"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#657B83"}},">")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),g=s("p",null,"Pretty neat, right? To some extent, anything your editor can show you about code, Twoslash can show. For example, here is the real auto-complete for a VitePress config:",-1),B=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(property) ti: any"},"ti")]),s("span",{style:{color:"#839496"}},",")]),s("div",{class:"meta-line"},[l("      "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tle")])]),s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tleTemplate")])])])])]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"})")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(property) ti: any"},"ti")]),s("span",{style:{color:"#657B83"}},",")]),s("div",{class:"meta-line"},[l("      "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tle")])]),s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tleTemplate")])])])])]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),m=e(`

    The name Twoslash refers to specially formatted comments (e.g. // ^?) which can be used to set up your environment, like compiler flags or separate input files. It couldn't be easier to set up and start creating incredible code examples!

    Install

    Install @andatoshiki/vitepress-plugin-shiki-twoslash (requires vitepress@>=1.0.0-alpha.61).

    bash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    bash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    bash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash

    WARNING

    Until shiki-twoslash uses the same version of shiki as VitePress, you must override the following packages' shiki versions for syntax highlighting to look the same.

    json
    {
    -    "pnpm": {
    -        "overrides": {
    -            "remark-shiki-twoslash>shiki": "^0.14.1",
    -            "shiki-twoslash>shiki": "^0.14.1"
    -        }
    -    }
    -}
    {
    -    "pnpm": {
    -        "overrides": {
    -            "remark-shiki-twoslash>shiki": "^0.14.1",
    -            "shiki-twoslash>shiki": "^0.14.1"
    -        }
    -    }
    -}

    Tracked in an upstream issue: https://github.com/shikijs/twoslash/issues/180

    Configure

    First, wrap your VitePress config file with the withTwoslash wrapper.

    `,7),f=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#839496"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"// Your VitePress config")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#657B83"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"// Your VitePress config")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),v=s("p",null,[l("Then, import "),s("code",null,"@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css"),l(" into your theme.")],-1),b=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// .vitepress/theme/index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { - Layout: DefineComponent; - enhanceApp: (ctx: EnhanceAppContext) => void; -} -import defaultTheme`},"defaultTheme")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress/theme'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { - Layout: DefineComponent; - enhanceApp: (ctx: EnhanceAppContext) => void; -} -import defaultTheme`},"defaultTheme")])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// .vitepress/theme/index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { - Layout: DefineComponent; - enhanceApp: (ctx: EnhanceAppContext) => void; -} -import defaultTheme`},"defaultTheme")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress/theme'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { - Layout: DefineComponent; - enhanceApp: (ctx: EnhanceAppContext) => void; -} -import defaultTheme`},"defaultTheme")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),C=e(`

    TIP

    You can configure VitePress Twoslash using the twoslash property added to defineConfig.

    Add Twoslash

    Finally, add the twoslash attribute to markdown fenced code blocks.

    md
    \`\`\`ts twoslash
    -// Removes 'readonly' attributes from a type's properties
    -type CreateMutable<Type> = {
    -    -readonly [Property in keyof Type]: Type[Property]
    -}
    -
    -type LockedAccount = {
    -    readonly id: string
    -    readonly name: string
    -}
    -
    -type UnlockedAccount = CreateMutable<LockedAccount>
    -//   ^?
    -\`\`\`
    \`\`\`ts twoslash
    -// Removes 'readonly' attributes from a type's properties
    -type CreateMutable<Type> = {
    -    -readonly [Property in keyof Type]: Type[Property]
    -}
    -
    -type LockedAccount = {
    -    readonly id: string
    -    readonly name: string
    -}
    -
    -type UnlockedAccount = CreateMutable<LockedAccount>
    -//   ^?
    -\`\`\`

    And your code blocks will be twoslashified!

    `,5),k=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#839496"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"> "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"-"),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}}," ["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"in"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"keyof"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"]"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#839496"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}},[l(),s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}},[l(),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type UnlockedAccount = { - id: string; - name: string; -}`,style:{"border-bottom":"solid 2px lightgrey"}},"UnlockedAccount")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#839496"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#839496"}},">")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l(`type UnlockedAccount = { - id: string; - name: string; -}`)])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#657B83"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"> "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"-"),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}}," ["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"in"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"keyof"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"]"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#657B83"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}},[l(),s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}},[l(),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type UnlockedAccount = { - id: string; - name: string; -}`,style:{"border-bottom":"solid 2px lightgrey"}},"UnlockedAccount")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#657B83"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#657B83"}},">")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l(`type UnlockedAccount = { - id: string; - name: string; -}`)])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br")])],-1);function A(T,w,P,_,D,x){const a=o;return p(),t("div",null,[i,r(a,{readTime:"2",words:"437"}),y,d,u,h,g,B,m,f,v,b,C,k])}const V=n(c,[["render",A]]);export{M as __pageData,V as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_index.md.7fc07d32.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_index.md.7fc07d32.lean.js deleted file mode 100644 index 36362118..00000000 --- a/assets/application_vitepress-plugin-shiki-twoslash_index.md.7fc07d32.lean.js +++ /dev/null @@ -1,71 +0,0 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as p,c as t,H as r,k as s,a as l,Q as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const M=JSON.parse('{"title":"VitePress Twoslash: VitePress Plugin for Shiki Twoslash","titleTemplate":false,"description":"Static code examples for VitePress using Shiki Twoslash.","frontmatter":{"description":"Static code examples for VitePress using Shiki Twoslash.","title":"VitePress Twoslash: VitePress Plugin for Shiki Twoslash","titleTemplate":false,"keywords":["getting-started","intro"]},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/index.md","filePath":"application/vitepress-plugin-shiki-twoslash/index.md","lastUpdated":1695377563000}'),c={name:"application/vitepress-plugin-shiki-twoslash/index.md"},i=s("h1",{id:"andatoshiki-vitepress-plugin-shiki-twoslash",tabindex:"-1"},[l("@andatoshiki/vitepress-plugin-shiki-twoslash "),s("a",{class:"header-anchor",href:"#andatoshiki-vitepress-plugin-shiki-twoslash","aria-label":'Permalink to "@andatoshiki/vitepress-plugin-shiki-twoslash"'},"​")],-1),y=s("blockquote",null,[s("p",null,[l("Static code examples for "),s("a",{href:"https://vitepress.dev",target:"_blank",rel:"noreferrer"},"VitePress"),l(" using "),s("a",{href:"https://github.com/shikijs/twoslash",target:"_blank",rel:"noreferrer"},"Shiki Twoslash"),l(" — powered by the syntax engine of Visual Studio Code and the TypeScript compiler.")])],-1),d=s("h2",{id:"overview",tabindex:"-1"},[l("Overview "),s("a",{class:"header-anchor",href:"#overview","aria-label":'Permalink to "Overview"'},"​")],-1),u=s("p",null,"Try moving your cursor into the code block below:",-1),h=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#839496"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"> "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"-"),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}}," ["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"in"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"keyof"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"]"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#839496"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}},[l(),s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}},[l(),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type UnlockedAccount = { - id: string; - name: string; -}`},"UnlockedAccount")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#839496"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#839496"}},">")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#657B83"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"> "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"-"),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}}," ["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"in"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"keyof"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"]"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#657B83"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}},[l(),s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}},[l(),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type UnlockedAccount = { - id: string; - name: string; -}`},"UnlockedAccount")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#657B83"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#657B83"}},">")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),g=s("p",null,"Pretty neat, right? To some extent, anything your editor can show you about code, Twoslash can show. For example, here is the real auto-complete for a VitePress config:",-1),B=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(property) ti: any"},"ti")]),s("span",{style:{color:"#839496"}},",")]),s("div",{class:"meta-line"},[l("      "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tle")])]),s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tleTemplate")])])])])]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"})")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:"(property) ti: any"},"ti")]),s("span",{style:{color:"#657B83"}},",")]),s("div",{class:"meta-line"},[l("      "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tle")])]),s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tleTemplate")])])])])]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),m=e("",7),f=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#839496"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#839496"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#839496"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#586E75"}},"// Your VitePress config")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},")")])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," { "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#657B83"}}," } "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> -import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#657B83"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig -import defineConfig`},"defineConfig")]),s("span",{style:{color:"#657B83"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#93A1A1"}},"// Your VitePress config")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),v=s("p",null,[l("Then, import "),s("code",null,"@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css"),l(" into your theme.")],-1),b=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// .vitepress/theme/index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { - Layout: DefineComponent; - enhanceApp: (ctx: EnhanceAppContext) => void; -} -import defaultTheme`},"defaultTheme")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress/theme'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { - Layout: DefineComponent; - enhanceApp: (ctx: EnhanceAppContext) => void; -} -import defaultTheme`},"defaultTheme")])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// .vitepress/theme/index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { - Layout: DefineComponent; - enhanceApp: (ctx: EnhanceAppContext) => void; -} -import defaultTheme`},"defaultTheme")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"from"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'vitepress/theme'")]),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"import"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#2AA198"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#859900"}},"export"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"default"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#268BD2"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { - Layout: DefineComponent; - enhanceApp: (ctx: EnhanceAppContext) => void; -} -import defaultTheme`},"defaultTheme")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),C=e("",5),k=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki solarized-dark twoslash lsp",style:{"background-color":"#002B36",color:"#839496"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#839496"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"> "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"-"),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}}," ["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"in"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"keyof"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"]"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#839496"}},"["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#839496"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}},[l(),s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#93A1A1"}},"readonly"),s("span",{style:{color:"#839496"}},[l(),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#839496"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"type"),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type UnlockedAccount = { - id: string; - name: string; -}`,style:{"border-bottom":"solid 2px lightgrey"}},"UnlockedAccount")]),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#839496"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#839496"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#839496"}},">")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l(`type UnlockedAccount = { - id: string; - name: string; -}`)])])])])]),s("pre",{class:"shiki solarized-light twoslash lsp",style:{"background-color":"#FDF6E3",color:"#657B83"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#93A1A1"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#657B83"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"> "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"-"),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}}," ["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"in"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"keyof"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"]"),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#657B83"}},"["),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#657B83"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}},[l(),s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#586E75"}},"readonly"),s("span",{style:{color:"#657B83"}},[l(),s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#859900"}},":"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#657B83"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#586E75"}},"type"),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type UnlockedAccount = { - id: string; - name: string; -}`,style:{"border-bottom":"solid 2px lightgrey"}},"UnlockedAccount")]),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#859900"}},"="),s("span",{style:{color:"#657B83"}}," "),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#657B83"}},"<"),s("span",{style:{color:"#CB4B16"}},[s("data-lsp",{lsp:`type LockedAccount = { - readonly id: string; - readonly name: string; -}`},"LockedAccount")]),s("span",{style:{color:"#657B83"}},">")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l(`type UnlockedAccount = { - id: string; - name: string; -}`)])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br")])],-1);function A(T,w,P,_,D,x){const a=o;return p(),t("div",null,[i,r(a,{readTime:"2",words:"437"}),y,d,u,h,g,B,m,f,v,b,C,k])}const V=n(c,[["render",A]]);export{M as __pageData,V as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_index.md.e8d8a5ec.js b/assets/application_vitepress-plugin-shiki-twoslash_index.md.e8d8a5ec.js new file mode 100644 index 00000000..dabe0d5d --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_index.md.e8d8a5ec.js @@ -0,0 +1,111 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as p,c as t,H as r,k as s,a as l,Q as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const M=JSON.parse('{"title":"VitePress Twoslash: VitePress Plugin for Shiki Twoslash","titleTemplate":false,"description":"Static code examples for VitePress using Shiki Twoslash.","frontmatter":{"description":"Static code examples for VitePress using Shiki Twoslash.","title":"VitePress Twoslash: VitePress Plugin for Shiki Twoslash","titleTemplate":false,"keywords":["getting-started","intro"]},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/index.md","filePath":"application/vitepress-plugin-shiki-twoslash/index.md","lastUpdated":1699051935000}'),c={name:"application/vitepress-plugin-shiki-twoslash/index.md"},i=s("h1",{id:"andatoshiki-vitepress-plugin-shiki-twoslash",tabindex:"-1"},[l("@andatoshiki/vitepress-plugin-shiki-twoslash "),s("a",{class:"header-anchor",href:"#andatoshiki-vitepress-plugin-shiki-twoslash","aria-label":'Permalink to "@andatoshiki/vitepress-plugin-shiki-twoslash"'},"​")],-1),y=s("blockquote",null,[s("p",null,[l("Static code examples for "),s("a",{href:"https://vitepress.dev",target:"_blank",rel:"noreferrer"},"VitePress"),l(" using "),s("a",{href:"https://github.com/shikijs/twoslash",target:"_blank",rel:"noreferrer"},"Shiki Twoslash"),l(" — powered by the syntax engine of Visual Studio Code and the TypeScript compiler.")])],-1),d=s("h2",{id:"overview",tabindex:"-1"},[l("Overview "),s("a",{class:"header-anchor",href:"#overview","aria-label":'Permalink to "Overview"'},"​")],-1),u=s("p",null,"Try moving your cursor into the code block below:",-1),A=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#ADBAC7"}},"<"),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"> "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"-readonly"),s("span",{style:{color:"#ADBAC7"}}," ["),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"in"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"keyof"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"]"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"["),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#ADBAC7"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"readonly"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"readonly"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type UnlockedAccount = { + id: string; + name: string; +}`},"UnlockedAccount")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#ADBAC7"}},"<"),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#ADBAC7"}},">")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#24292E"}},"<"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"> "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"-readonly"),s("span",{style:{color:"#24292E"}}," ["),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"in"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"keyof"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"]"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"["),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#24292E"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"readonly"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"readonly"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type UnlockedAccount = { + id: string; + name: string; +}`},"UnlockedAccount")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#24292E"}},"<"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#24292E"}},">")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),h=s("p",null,"Pretty neat, right? To some extent, anything your editor can show you about code, Twoslash can show. For example, here is the real auto-complete for a VitePress config:",-1),C=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#F69D50"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"(property) ti: any"},"ti")]),s("span",{style:{color:"#F69D50"}},",")]),s("div",{class:"meta-line"},[l("      "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tle")])]),s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tleTemplate")])])])])]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}},"})")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[l(" "),s("data-lsp",{lsp:"(property) ti: any"},"ti"),l(",")])]),s("div",{class:"meta-line"},[l("      "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tle")])]),s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tleTemplate")])])])])]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),m=e(`

    The name Twoslash refers to specially formatted comments (e.g. // ^?) which can be used to set up your environment, like compiler flags or separate input files. It couldn't be easier to set up and start creating incredible code examples!

    Install

    Install @andatoshiki/vitepress-plugin-shiki-twoslash (requires vitepress@>=1.0.0-alpha.61).

    bash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    bash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    bash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash

    WARNING

    Until shiki-twoslash uses the same version of shiki as VitePress, you must override the following packages' shiki versions for syntax highlighting to look the same.

    json
    {
    +    "pnpm": {
    +        "overrides": {
    +            "remark-shiki-twoslash>shiki": "^0.14.1",
    +            "shiki-twoslash>shiki": "^0.14.1"
    +        }
    +    }
    +}
    {
    +    "pnpm": {
    +        "overrides": {
    +            "remark-shiki-twoslash>shiki": "^0.14.1",
    +            "shiki-twoslash>shiki": "^0.14.1"
    +        }
    +    }
    +}

    Tracked in an upstream issue: https://github.com/shikijs/twoslash/issues/180

    Configure

    First, wrap your VitePress config file with the withTwoslash wrapper.

    `,7),g=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#F69D50"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#F69D50"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#768390"}},"// Your VitePress config")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}},")")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#24292E"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// Your VitePress config")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),D=s("p",null,[l("Then, import "),s("code",null,"@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css"),l(" into your theme.")],-1),f=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// .vitepress/theme/index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:`(alias) const defaultTheme: { + Layout: DefineComponent; + enhanceApp: (ctx: EnhanceAppContext) => void; +} +import defaultTheme`},"defaultTheme"),l()]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress/theme'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { + Layout: DefineComponent; + enhanceApp: (ctx: EnhanceAppContext) => void; +} +import defaultTheme`},"defaultTheme")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// .vitepress/theme/index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:`(alias) const defaultTheme: { + Layout: DefineComponent; + enhanceApp: (ctx: EnhanceAppContext) => void; +} +import defaultTheme`},"defaultTheme"),l()]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress/theme'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:`(alias) const defaultTheme: { + Layout: DefineComponent; + enhanceApp: (ctx: EnhanceAppContext) => void; +} +import defaultTheme`},"defaultTheme")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),v=e(`

    TIP

    You can configure VitePress Twoslash using the twoslash property added to defineConfig.

    Add Twoslash

    Finally, add the twoslash attribute to markdown fenced code blocks.

    md
    \`\`\`ts twoslash
    +// Removes 'readonly' attributes from a type's properties
    +type CreateMutable<Type> = {
    +    -readonly [Property in keyof Type]: Type[Property]
    +}
    +
    +type LockedAccount = {
    +    readonly id: string
    +    readonly name: string
    +}
    +
    +type UnlockedAccount = CreateMutable<LockedAccount>
    +//   ^?
    +\`\`\`
    \`\`\`ts twoslash
    +// Removes 'readonly' attributes from a type's properties
    +type CreateMutable<Type> = {
    +    -readonly [Property in keyof Type]: Type[Property]
    +}
    +
    +type LockedAccount = {
    +    readonly id: string
    +    readonly name: string
    +}
    +
    +type UnlockedAccount = CreateMutable<LockedAccount>
    +//   ^?
    +\`\`\`

    And your code blocks will be twoslashified!

    `,5),b=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#ADBAC7"}},"<"),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"> "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"-readonly"),s("span",{style:{color:"#ADBAC7"}}," ["),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"in"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"keyof"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"]"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"["),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#ADBAC7"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"readonly"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"readonly"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type UnlockedAccount = { + id: string; + name: string; +}`,style:{"border-bottom":"solid 2px lightgrey"}},"UnlockedAccount")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#ADBAC7"}},"<"),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#ADBAC7"}},">")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l(`type UnlockedAccount = { + id: string; + name: string; +}`)])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#24292E"}},"<"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"> "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"-readonly"),s("span",{style:{color:"#24292E"}}," ["),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"in"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"keyof"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"]"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"["),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#24292E"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"readonly"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"readonly"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type UnlockedAccount = { + id: string; + name: string; +}`,style:{"border-bottom":"solid 2px lightgrey"}},"UnlockedAccount")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#24292E"}},"<"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#24292E"}},">")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l(`type UnlockedAccount = { + id: string; + name: string; +}`)])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br")])],-1);function F(k,T,E,B,w,P){const a=o;return p(),t("div",null,[i,r(a,{readTime:"2",words:"437"}),y,d,u,A,h,C,m,g,D,f,v,b])}const q=n(c,[["render",F]]);export{M as __pageData,q as default}; diff --git a/assets/application_vitepress-plugin-shiki-twoslash_index.md.e8d8a5ec.lean.js b/assets/application_vitepress-plugin-shiki-twoslash_index.md.e8d8a5ec.lean.js new file mode 100644 index 00000000..791e3b7a --- /dev/null +++ b/assets/application_vitepress-plugin-shiki-twoslash_index.md.e8d8a5ec.lean.js @@ -0,0 +1,71 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as p,c as t,H as r,k as s,a as l,Q as e}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const M=JSON.parse('{"title":"VitePress Twoslash: VitePress Plugin for Shiki Twoslash","titleTemplate":false,"description":"Static code examples for VitePress using Shiki Twoslash.","frontmatter":{"description":"Static code examples for VitePress using Shiki Twoslash.","title":"VitePress Twoslash: VitePress Plugin for Shiki Twoslash","titleTemplate":false,"keywords":["getting-started","intro"]},"headers":[],"relativePath":"application/vitepress-plugin-shiki-twoslash/index.md","filePath":"application/vitepress-plugin-shiki-twoslash/index.md","lastUpdated":1699051935000}'),c={name:"application/vitepress-plugin-shiki-twoslash/index.md"},i=s("h1",{id:"andatoshiki-vitepress-plugin-shiki-twoslash",tabindex:"-1"},[l("@andatoshiki/vitepress-plugin-shiki-twoslash "),s("a",{class:"header-anchor",href:"#andatoshiki-vitepress-plugin-shiki-twoslash","aria-label":'Permalink to "@andatoshiki/vitepress-plugin-shiki-twoslash"'},"​")],-1),y=s("blockquote",null,[s("p",null,[l("Static code examples for "),s("a",{href:"https://vitepress.dev",target:"_blank",rel:"noreferrer"},"VitePress"),l(" using "),s("a",{href:"https://github.com/shikijs/twoslash",target:"_blank",rel:"noreferrer"},"Shiki Twoslash"),l(" — powered by the syntax engine of Visual Studio Code and the TypeScript compiler.")])],-1),d=s("h2",{id:"overview",tabindex:"-1"},[l("Overview "),s("a",{class:"header-anchor",href:"#overview","aria-label":'Permalink to "Overview"'},"​")],-1),u=s("p",null,"Try moving your cursor into the code block below:",-1),A=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#ADBAC7"}},"<"),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"> "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"-readonly"),s("span",{style:{color:"#ADBAC7"}}," ["),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"in"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"keyof"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"]"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"["),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#ADBAC7"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"readonly"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"readonly"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type UnlockedAccount = { + id: string; + name: string; +}`},"UnlockedAccount")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#ADBAC7"}},"<"),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#ADBAC7"}},">")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#24292E"}},"<"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"> "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"-readonly"),s("span",{style:{color:"#24292E"}}," ["),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"in"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"keyof"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"]"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"["),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#24292E"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"readonly"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"readonly"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type UnlockedAccount = { + id: string; + name: string; +}`},"UnlockedAccount")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#24292E"}},"<"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#24292E"}},">")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),h=s("p",null,"Pretty neat, right? To some extent, anything your editor can show you about code, Twoslash can show. For example, here is the real auto-complete for a VitePress config:",-1),C=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#F69D50"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:"(property) ti: any"},"ti")]),s("span",{style:{color:"#F69D50"}},",")]),s("div",{class:"meta-line"},[l("      "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tle")])]),s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tleTemplate")])])])])]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}},"})")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},[l(" "),s("data-lsp",{lsp:"(property) ti: any"},"ti"),l(",")])]),s("div",{class:"meta-line"},[l("      "),s("span",{class:"inline-completions"},[s("ul",{class:"dropdown"},[s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tle")])]),s("li",{class:""},[s("span",null,[s("span",{class:"result-found"},"ti"),l("tleTemplate")])])])])]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"})")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),m=e("",7),g=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(" { "),s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash"),l(" } ")]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#F69D50"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#DCBDFB"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#F69D50"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#768390"}},"// Your VitePress config")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#F69D50"}},")")])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// .vitepress/config.[ext]")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(" { "),s("data-lsp",{lsp:`(alias) function withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash"),l(" } ")]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) withTwoslash(config: UserConfig): Promise> +import withTwoslash`},"withTwoslash")]),s("span",{style:{color:"#24292E"}},"(")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`(alias) defineConfig(config: UserConfig): UserConfig +import defineConfig`},"defineConfig")]),s("span",{style:{color:"#24292E"}},"({")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6A737D"}},"// Your VitePress config")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," })")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},")")])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),D=s("p",null,[l("Then, import "),s("code",null,"@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css"),l(" into your theme.")],-1),f=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// .vitepress/theme/index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}},[l(),s("data-lsp",{lsp:`(alias) const defaultTheme: { + Layout: DefineComponent; + enhanceApp: (ctx: EnhanceAppContext) => void; +} +import defaultTheme`},"defaultTheme"),l()]),s("span",{style:{color:"#F47067"}},"from"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'vitepress/theme'")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"import"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"export"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#F47067"}},"default"),s("span",{style:{color:"#F69D50"}}," "),s("span",{style:{color:"#ADBAC7"}},[s("data-lsp",{lsp:`(alias) const defaultTheme: { + Layout: DefineComponent; + enhanceApp: (ctx: EnhanceAppContext) => void; +} +import defaultTheme`},"defaultTheme")])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// .vitepress/theme/index.ts")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:`(alias) const defaultTheme: { + Layout: DefineComponent; + enhanceApp: (ctx: EnhanceAppContext) => void; +} +import defaultTheme`},"defaultTheme"),l()]),s("span",{style:{color:"#D73A49"}},"from"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'vitepress/theme'")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"import"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#032F62"}},"'@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"export"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"default"),s("span",{style:{color:"#24292E"}},[l(),s("data-lsp",{lsp:`(alias) const defaultTheme: { + Layout: DefineComponent; + enhanceApp: (ctx: EnhanceAppContext) => void; +} +import defaultTheme`},"defaultTheme")])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br")])],-1),v=e("",5),b=s("div",{class:"language-ts vp-adaptive-theme line-numbers-mode"},[s("button",{title:"Copy Code",class:"copy"}),s("span",{class:"lang"},"ts"),s("pre",{class:"shiki github-dark-dimmed twoslash lsp",style:{"background-color":"#22272e",color:"#adbac7"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#768390"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#ADBAC7"}},"<"),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"> "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"-readonly"),s("span",{style:{color:"#ADBAC7"}}," ["),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"in"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"keyof"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"]"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#ADBAC7"}},"["),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#ADBAC7"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"readonly"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"readonly"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#F47067"}},"type"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type UnlockedAccount = { + id: string; + name: string; +}`,style:{"border-bottom":"solid 2px lightgrey"}},"UnlockedAccount")]),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#ADBAC7"}},"<"),s("span",{style:{color:"#F69D50"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#ADBAC7"}},">")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l(`type UnlockedAccount = { + id: string; + name: string; +}`)])])])])]),s("pre",{class:"shiki github-light twoslash lsp",style:{"background-color":"#fff",color:"#24292e"}},[s("div",{class:"language-id"},"ts"),s("div",{class:"code-container"},[s("code",null,[s("div",{class:"line"},[s("span",{style:{color:"#6A737D"}},"// Removes 'readonly' attributes from a type's properties")]),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#24292E"}},"<"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"> "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"-readonly"),s("span",{style:{color:"#24292E"}}," ["),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"in"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"keyof"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"]"),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Type in type CreateMutable"},"Type")]),s("span",{style:{color:"#24292E"}},"["),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"(type parameter) Property"},"Property")]),s("span",{style:{color:"#24292E"}},"]")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," {")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"readonly"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) id: string"},"id")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"readonly"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#E36209"}},[s("data-lsp",{lsp:"(property) name: string"},"name")]),s("span",{style:{color:"#D73A49"}},":"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#005CC5"}},"string")]),s("div",{class:"line"},[s("span",{style:{color:"#24292E"}},"}")]),s("div",{class:"line"}," "),s("div",{class:"line"},[s("span",{style:{color:"#D73A49"}},"type"),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type UnlockedAccount = { + id: string; + name: string; +}`,style:{"border-bottom":"solid 2px lightgrey"}},"UnlockedAccount")]),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#D73A49"}},"="),s("span",{style:{color:"#24292E"}}," "),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:"type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }"},"CreateMutable")]),s("span",{style:{color:"#24292E"}},"<"),s("span",{style:{color:"#6F42C1"}},[s("data-lsp",{lsp:`type LockedAccount = { + readonly id: string; + readonly name: string; +}`},"LockedAccount")]),s("span",{style:{color:"#24292E"}},">")]),s("div",{class:"meta-line"},[s("span",{class:"popover-prefix"}," "),s("span",{class:"popover"},[s("div",{class:"arrow"}),l(`type UnlockedAccount = { + id: string; + name: string; +}`)])])])])]),s("div",{class:"line-numbers-wrapper","aria-hidden":"true"},[s("span",{class:"line-number"},"1"),s("br"),s("span",{class:"line-number"},"2"),s("br"),s("span",{class:"line-number"},"3"),s("br"),s("span",{class:"line-number"},"4"),s("br")])],-1);function F(k,T,E,B,w,P){const a=o;return p(),t("div",null,[i,r(a,{readTime:"2",words:"437"}),y,d,u,A,h,C,m,g,D,f,v,b])}const q=n(c,[["render",F]]);export{M as __pageData,q as default}; diff --git a/assets/chunks/VPAlgoliaSearchBox.a4c0242a.js b/assets/chunks/VPAlgoliaSearchBox.c32b1d6a.js similarity index 99% rename from assets/chunks/VPAlgoliaSearchBox.a4c0242a.js rename to assets/chunks/VPAlgoliaSearchBox.c32b1d6a.js index a38883c6..51dfc6f8 100644 --- a/assets/chunks/VPAlgoliaSearchBox.a4c0242a.js +++ b/assets/chunks/VPAlgoliaSearchBox.c32b1d6a.js @@ -1,4 +1,4 @@ -import{d as so,al as fo,K as mo,j as po,x as vo,o as ho,c as yo}from"./framework.b7580407.js";import{u as go}from"./theme.7de1b093.js";/*! @docsearch/js 3.5.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */function un(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(o){return Object.getOwnPropertyDescriptor(t,o).enumerable})),n.push.apply(n,r)}return n}function I(t){for(var e=1;e=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function se(t,e){return function(n){if(Array.isArray(n))return n}(t)||function(n,r){var o=n==null?null:typeof Symbol<"u"&&n[Symbol.iterator]||n["@@iterator"];if(o!=null){var i,a,u=[],c=!0,s=!1;try{for(o=o.call(n);!(c=(i=o.next()).done)&&(u.push(i.value),!r||u.length!==r);c=!0);}catch(l){s=!0,a=l}finally{try{c||o.return==null||o.return()}finally{if(s)throw a}}return u}}(t,e)||yr(t,e)||function(){throw new TypeError(`Invalid attempt to destructure non-iterable instance. +import{d as so,al as fo,K as mo,j as po,x as vo,o as ho,c as yo}from"./framework.b7580407.js";import{u as go}from"./theme.c3ca1c74.js";/*! @docsearch/js 3.5.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */function un(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(o){return Object.getOwnPropertyDescriptor(t,o).enumerable})),n.push.apply(n,r)}return n}function I(t){for(var e=1;e=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function se(t,e){return function(n){if(Array.isArray(n))return n}(t)||function(n,r){var o=n==null?null:typeof Symbol<"u"&&n[Symbol.iterator]||n["@@iterator"];if(o!=null){var i,a,u=[],c=!0,s=!1;try{for(o=o.call(n);!(c=(i=o.next()).done)&&(u.push(i.value),!r||u.length!==r);c=!0);}catch(l){s=!0,a=l}finally{try{c||o.return==null||o.return()}finally{if(s)throw a}}return u}}(t,e)||yr(t,e)||function(){throw new TypeError(`Invalid attempt to destructure non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function ft(t){return function(e){if(Array.isArray(e))return Lt(e)}(t)||function(e){if(typeof Symbol<"u"&&e[Symbol.iterator]!=null||e["@@iterator"]!=null)return Array.from(e)}(t)||yr(t)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function yr(t,e){if(t){if(typeof t=="string")return Lt(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return n==="Object"&&t.constructor&&(n=t.constructor.name),n==="Map"||n==="Set"?Array.from(t):n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Lt(t,e):void 0}}function Lt(t,e){(e==null||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n3)for(n=[n],i=3;i0?Ie(v.type,v.props,v.key,null,v.__v):v)!=null){if(v.__=n,v.__b=n.__b+1,(p=b[l])===null||p&&v.key==p.key&&v.type===p.type)b[l]=void 0;else for(m=0;m<_;m++){if((p=b[m])&&v.key==p.key&&v.type===p.type){b[m]=void 0;break}p=null}Yt(t,v,p=p||mt,o,i,a,u,c,s),d=v.__e,(m=v.ref)&&p.ref!=m&&(y||(y=[]),p.ref&&y.push(p.ref,null,v),y.push(m,v.__c||d,v)),d!=null?(h==null&&(h=d),typeof v.type=="function"&&v.__k!=null&&v.__k===p.__k?v.__d=c=wr(v,c,t):c=jr(t,v,p,b,d,c),s||n.type!=="option"?typeof n.type=="function"&&(n.__d=c):t.value=""):c&&p.__e==c&&c.parentNode!=t&&(c=We(p))}for(n.__e=h,l=_;l--;)b[l]!=null&&(typeof n.type=="function"&&b[l].__e!=null&&b[l].__e==n.__d&&(n.__d=We(r,l+1)),Ir(b[l],b[l]));if(y)for(l=0;l3)for(n=[n],i=3;i=n.__.length&&n.__.push({}),n.__[t]}function kr(t){return pe=1,Ar(xr,t)}function Ar(t,e,n){var r=Je(de++,2);return r.t=t,r.__c||(r.__=[n?n(e):xr(void 0,e),function(o){var i=r.t(r.__[0],o);r.__[0]!==i&&(r.__=[i,r.__[1]],r.__c.setState({}))}],r.__c=q),r.__}function Cr(t,e){var n=Je(de++,3);!w.__s&&Gt(n.__H,e)&&(n.__=t,n.__H=e,q.__H.__h.push(n))}function bn(t,e){var n=Je(de++,4);!w.__s&&Gt(n.__H,e)&&(n.__=t,n.__H=e,q.__h.push(n))}function Pt(t,e){var n=Je(de++,7);return Gt(n.__H,e)&&(n.__=t(),n.__H=e,n.__h=t),n.__}function Eo(){Ht.forEach(function(t){if(t.__P)try{t.__H.__h.forEach(ct),t.__H.__h.forEach(Ut),t.__H.__h=[]}catch(e){t.__H.__h=[],w.__e(e,t.__v)}}),Ht=[]}w.__b=function(t){q=null,vn&&vn(t)},w.__r=function(t){dn&&dn(t),de=0;var e=(q=t.__c).__H;e&&(e.__h.forEach(ct),e.__h.forEach(Ut),e.__h=[])},w.diffed=function(t){hn&&hn(t);var e=t.__c;e&&e.__H&&e.__H.__h.length&&(Ht.push(e)!==1&&pn===w.requestAnimationFrame||((pn=w.requestAnimationFrame)||function(n){var r,o=function(){clearTimeout(i),_n&&cancelAnimationFrame(r),setTimeout(n)},i=setTimeout(o,100);_n&&(r=requestAnimationFrame(o))})(Eo)),q=void 0},w.__c=function(t,e){e.some(function(n){try{n.__h.forEach(ct),n.__h=n.__h.filter(function(r){return!r.__||Ut(r)})}catch(r){e.some(function(o){o.__h&&(o.__h=[])}),e=[],w.__e(r,n.__v)}}),yn&&yn(t,e)},w.unmount=function(t){gn&&gn(t);var e=t.__c;if(e&&e.__H)try{e.__H.__.forEach(ct)}catch(n){w.__e(n,e.__v)}};var _n=typeof requestAnimationFrame=="function";function ct(t){var e=q;typeof t.__c=="function"&&t.__c(),q=e}function Ut(t){var e=q;t.__c=t.__(),q=e}function Gt(t,e){return!t||t.length!==e.length||e.some(function(n,r){return n!==t[r]})}function xr(t,e){return typeof e=="function"?e(t):e}function Nr(t,e){for(var n in e)t[n]=e[n];return t}function Ft(t,e){for(var n in t)if(n!=="__source"&&!(n in e))return!0;for(var r in e)if(r!=="__source"&&t[r]!==e[r])return!0;return!1}function Bt(t){this.props=t}(Bt.prototype=new K).isPureReactComponent=!0,Bt.prototype.shouldComponentUpdate=function(t,e){return Ft(this.props,t)||Ft(this.state,e)};var On=w.__b;w.__b=function(t){t.type&&t.type.__f&&t.ref&&(t.props.ref=t.ref,t.ref=null),On&&On(t)};var Po=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.forward_ref")||3911,Sn=function(t,e){return t==null?null:$($(t).map(e))},Io={map:Sn,forEach:Sn,count:function(t){return t?$(t).length:0},only:function(t){var e=$(t);if(e.length!==1)throw"Children.only";return e[0]},toArray:$},Do=w.__e;function ut(){this.__u=0,this.t=null,this.__b=null}function Tr(t){var e=t.__.__c;return e&&e.__e&&e.__e(t)}function je(){this.u=null,this.o=null}w.__e=function(t,e,n){if(t.then){for(var r,o=e;o=o.__;)if((r=o.__c)&&r.__c)return e.__e==null&&(e.__e=n.__e,e.__k=n.__k),r.__c(t,e)}Do(t,e,n)},(ut.prototype=new K).__c=function(t,e){var n=e.__c,r=this;r.t==null&&(r.t=[]),r.t.push(n);var o=Tr(r.__v),i=!1,a=function(){i||(i=!0,n.componentWillUnmount=n.__c,o?o(u):u())};n.__c=n.componentWillUnmount,n.componentWillUnmount=function(){a(),n.__c&&n.__c()};var u=function(){if(!--r.__u){if(r.state.__e){var s=r.state.__e;r.__v.__k[0]=function m(p,v,d){return p&&(p.__v=null,p.__k=p.__k&&p.__k.map(function(h){return m(h,v,d)}),p.__c&&p.__c.__P===v&&(p.__e&&d.insertBefore(p.__e,p.__d),p.__c.__e=!0,p.__c.__P=d)),p}(s,s.__c.__P,s.__c.__O)}var l;for(r.setState({__e:r.__b=null});l=r.t.pop();)l.forceUpdate()}},c=e.__h===!0;r.__u++||c||r.setState({__e:r.__b=r.__v.__k[0]}),t.then(a,a)},ut.prototype.componentWillUnmount=function(){this.t=[]},ut.prototype.render=function(t,e){if(this.__b){if(this.__v.__k){var n=document.createElement("div"),r=this.__v.__k[0].__c;this.__v.__k[0]=function i(a,u,c){return a&&(a.__c&&a.__c.__H&&(a.__c.__H.__.forEach(function(s){typeof s.__c=="function"&&s.__c()}),a.__c.__H=null),(a=Nr({},a)).__c!=null&&(a.__c.__P===c&&(a.__c.__P=u),a.__c=null),a.__k=a.__k&&a.__k.map(function(s){return i(s,u,c)})),a}(this.__b,n,r.__O=r.__P)}this.__b=null}var o=e.__e&&W(X,null,t.fallback);return o&&(o.__h=null),[W(X,null,e.__e?null:t.children),o]};var wn=function(t,e,n){if(++n[1]===n[0]&&t.o.delete(e),t.props.revealOrder&&(t.props.revealOrder[0]!=="t"||!t.o.size))for(n=t.u;n;){for(;n.length>3;)n.pop()();if(n[1]>>1,1),e.i.removeChild(r)}}),Ke(W(ko,{context:e.context},t.__v),e.l)):e.l&&e.componentWillUnmount()}function Rr(t,e){return W(Ao,{__v:t,i:e})}(je.prototype=new K).__e=function(t){var e=this,n=Tr(e.__v),r=e.o.get(t);return r[0]++,function(o){var i=function(){e.props.revealOrder?(r.push(o),wn(e,t,r)):o()};n?n(i):i()}},je.prototype.render=function(t){this.u=null,this.o=new Map;var e=$(t.children);t.revealOrder&&t.revealOrder[0]==="b"&&e.reverse();for(var n=e.length;n--;)this.o.set(e[n],this.u=[1,0,this.u]);return t.children},je.prototype.componentDidUpdate=je.prototype.componentDidMount=function(){var t=this;this.o.forEach(function(e,n){wn(t,n,e)})};var qr=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.element")||60103,Co=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|fill|flood|font|glyph(?!R)|horiz|marker(?!H|W|U)|overline|paint|stop|strikethrough|stroke|text(?!L)|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,xo=function(t){return(typeof Symbol<"u"&&Ve(Symbol())=="symbol"?/fil|che|rad/i:/fil|che|ra/i).test(t)};function Lr(t,e,n){return e.__k==null&&(e.textContent=""),Ke(t,e),typeof n=="function"&&n(),t?t.__c:null}K.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(t){Object.defineProperty(K.prototype,t,{configurable:!0,get:function(){return this["UNSAFE_"+t]},set:function(e){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:e})}})});var jn=w.event;function No(){}function To(){return this.cancelBubble}function Ro(){return this.defaultPrevented}w.event=function(t){return jn&&(t=jn(t)),t.persist=No,t.isPropagationStopped=To,t.isDefaultPrevented=Ro,t.nativeEvent=t};var Mr,En={configurable:!0,get:function(){return this.class}},Pn=w.vnode;w.vnode=function(t){var e=t.type,n=t.props,r=n;if(typeof e=="string"){for(var o in r={},n){var i=n[o];o==="value"&&"defaultValue"in n&&i==null||(o==="defaultValue"&&"value"in n&&n.value==null?o="value":o==="download"&&i===!0?i="":/ondoubleclick/i.test(o)?o="ondblclick":/^onchange(textarea|input)/i.test(o+e)&&!xo(n.type)?o="oninput":/^on(Ani|Tra|Tou|BeforeInp)/.test(o)?o=o.toLowerCase():Co.test(o)?o=o.replace(/[A-Z0-9]/,"-$&").toLowerCase():i===null&&(i=void 0),r[o]=i)}e=="select"&&r.multiple&&Array.isArray(r.value)&&(r.value=$(n.children).forEach(function(a){a.props.selected=r.value.indexOf(a.props.value)!=-1})),e=="select"&&r.defaultValue!=null&&(r.value=$(n.children).forEach(function(a){a.props.selected=r.multiple?r.defaultValue.indexOf(a.props.value)!=-1:r.defaultValue==a.props.value})),t.props=r}e&&n.class!=n.className&&(En.enumerable="className"in n,n.className!=null&&(r.class=n.className),Object.defineProperty(r,"className",En)),t.$$typeof=qr,Pn&&Pn(t)};var In=w.__r;w.__r=function(t){In&&In(t),Mr=t.__c};var qo={ReactCurrentDispatcher:{current:{readContext:function(t){return Mr.__n[t.__c].props.value}}}};(typeof performance>"u"?"undefined":Ve(performance))=="object"&&typeof performance.now=="function"&&performance.now.bind(performance);function Dn(t){return!!t&&t.$$typeof===qr}var f={useState:kr,useReducer:Ar,useEffect:Cr,useLayoutEffect:bn,useRef:function(t){return pe=5,Pt(function(){return{current:t}},[])},useImperativeHandle:function(t,e,n){pe=6,bn(function(){typeof t=="function"?t(e()):t&&(t.current=e())},n==null?n:n.concat(t))},useMemo:Pt,useCallback:function(t,e){return pe=8,Pt(function(){return t},e)},useContext:function(t){var e=q.context[t.__c],n=Je(de++,9);return n.__c=t,e?(n.__==null&&(n.__=!0,e.sub(q)),e.props.value):t.__},useDebugValue:function(t,e){w.useDebugValue&&w.useDebugValue(e?e(t):t)},version:"16.8.0",Children:Io,render:Lr,hydrate:function(t,e,n){return Dr(t,e),typeof n=="function"&&n(),t?t.__c:null},unmountComponentAtNode:function(t){return!!t.__k&&(Ke(null,t),!0)},createPortal:Rr,createElement:W,createContext:function(t,e){var n={__c:e="__cC"+br++,__:t,Consumer:function(r,o){return r.children(o)},Provider:function(r){var o,i;return this.getChildContext||(o=[],(i={})[e]=this,this.getChildContext=function(){return i},this.shouldComponentUpdate=function(a){this.props.value!==a.value&&o.some(Mt)},this.sub=function(a){o.push(a);var u=a.componentWillUnmount;a.componentWillUnmount=function(){o.splice(o.indexOf(a),1),u&&u.call(a)}}),r.children}};return n.Provider.__=n.Consumer.contextType=n},createFactory:function(t){return W.bind(null,t)},cloneElement:function(t){return Dn(t)?jo.apply(null,arguments):t},createRef:function(){return{current:null}},Fragment:X,isValidElement:Dn,findDOMNode:function(t){return t&&(t.base||t.nodeType===1&&t)||null},Component:K,PureComponent:Bt,memo:function(t,e){function n(o){var i=this.props.ref,a=i==o.ref;return!a&&i&&(i.call?i(null):i.current=null),e?!e(this.props,o)||!a:Ft(this.props,o)}function r(o){return this.shouldComponentUpdate=n,W(t,o)}return r.displayName="Memo("+(t.displayName||t.name)+")",r.prototype.isReactComponent=!0,r.__f=!0,r},forwardRef:function(t){function e(n,r){var o=Nr({},n);return delete o.ref,t(o,(r=n.ref||r)&&(Ve(r)!="object"||"current"in r)?r:null)}return e.$$typeof=Po,e.render=e,e.prototype.isReactComponent=e.__f=!0,e.displayName="ForwardRef("+(t.displayName||t.name)+")",e},unstable_batchedUpdates:function(t,e){return t(e)},StrictMode:X,Suspense:ut,SuspenseList:je,lazy:function(t){var e,n,r;function o(i){if(e||(e=t()).then(function(a){n=a.default||a},function(a){r=a}),r)throw r;if(!n)throw e;return W(n,i)}return o.displayName="Lazy",o.__f=!0,o},__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:qo};function Lo(){return f.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},f.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}function Hr(){return f.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},f.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}var Mo=["translations"];function Vt(){return Vt=Object.assign||function(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);n=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var Fo=f.forwardRef(function(t,e){var n=t.translations,r=n===void 0?{}:n,o=Uo(t,Mo),i=r.buttonText,a=i===void 0?"Search":i,u=r.buttonAriaLabel,c=u===void 0?"Search":u,s=Ho(kr(null),2),l=s[0],m=s[1];return Cr(function(){typeof navigator<"u"&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?m("⌘"):m("Ctrl"))},[]),f.createElement("button",Vt({type:"button",className:"DocSearch DocSearch-Button","aria-label":c},o,{ref:e}),f.createElement("span",{className:"DocSearch-Button-Container"},f.createElement(Hr,null),f.createElement("span",{className:"DocSearch-Button-Placeholder"},a)),f.createElement("span",{className:"DocSearch-Button-Keys"},l!==null&&f.createElement(f.Fragment,null,f.createElement("kbd",{className:"DocSearch-Button-Key"},l==="Ctrl"?f.createElement(Lo,null):l),f.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))});function Ur(t,e){var n=void 0;return function(){for(var r=arguments.length,o=new Array(r),i=0;i(a(),l("span",{class:C(["VPBadge",e.type])},[u(e.$slots,"default",{},()=>[H(V(e.text),1)],!0)],2))}});const Qe=g(Ze,[["__scopeId","data-v-0d50132f"]]),et={key:0,class:"VPBackdrop"},tt=m({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(s){return(e,t)=>(a(),$(ue,{name:"fade"},{default:v(()=>[e.show?(a(),l("div",et)):f("",!0)]),_:1}))}});const st=g(tt,[["__scopeId","data-v-90d3771d"]]),P=De;function Ne(s,e){let t,n=!1;return()=>{t&&clearTimeout(t),n?t=setTimeout(s,e):(s(),(n=!0)&&setTimeout(()=>n=!1,e))}}function le(s){return/^\//.test(s)?s:`/${s}`}function Y(s){if(Fe(s))return s;const{site:e}=P(),{pathname:t,search:n,hash:o}=new URL(s,"http://a.com"),r=t.endsWith("/")||t.endsWith(".html")?s:s.replace(/(?:(^\.+)\/)?.*$/,`$1${t.replace(/(\.md)?$/,e.value.cleanUrls?"":".html")}${n}${o}`);return de(r)}function X({removeCurrent:s=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:n,page:o,theme:r}=P(),d=y(()=>{var _,k;return{label:(_=t.value.locales[n.value])==null?void 0:_.label,link:((k=t.value.locales[n.value])==null?void 0:k.link)||(n.value==="root"?"/":`/${n.value}/`)}});return{localeLinks:y(()=>Object.entries(t.value.locales).flatMap(([_,k])=>s&&d.value.label===k.label?[]:{text:k.label,link:nt(k.link||(_==="root"?"/":`/${_}/`),r.value.i18nRouting!==!1&&e,o.value.relativePath.slice(d.value.link.length-1),!t.value.cleanUrls)})),currentLang:d}}function nt(s,e,t,n){return e?s.replace(/\/$/,"")+le(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,n?".html":"")):s}const ot=s=>(z("data-v-3b0106a5"),s=s(),E(),s),at={class:"NotFound"},rt={class:"code"},it={class:"title"},lt=ot(()=>c("div",{class:"divider"},null,-1)),ct={class:"quote"},ut={class:"action"},dt=["href","aria-label"],_t=m({__name:"NotFound",setup(s){const{site:e,theme:t}=P(),{localeLinks:n}=X({removeCurrent:!1}),o=L("/");return F(()=>{var d;const r=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");n.value.length&&(o.value=((d=n.value.find(({link:p})=>p.startsWith(r)))==null?void 0:d.link)||n.value[0].link)}),(r,d)=>{var p,_,k,N,T;return a(),l("div",at,[c("p",rt,V(((p=i(t).notFound)==null?void 0:p.code)??"404"),1),c("h1",it,V(((_=i(t).notFound)==null?void 0:_.title)??"PAGE NOT FOUND"),1),lt,c("blockquote",ct,V(((k=i(t).notFound)==null?void 0:k.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),c("div",ut,[c("a",{class:"link",href:i(de)(o.value),"aria-label":((N=i(t).notFound)==null?void 0:N.linkLabel)??"go to home"},V(((T=i(t).notFound)==null?void 0:T.linkText)??"Take me home"),9,dt)])])}}});const vt=g(_t,[["__scopeId","data-v-3b0106a5"]]);function Ie(s,e){if(Array.isArray(s))return ee(s);if(s==null)return[];e=le(e);const t=Object.keys(s).sort((o,r)=>r.split("/").length-o.split("/").length).find(o=>e.startsWith(le(o))),n=t?s[t]:[];return Array.isArray(n)?ee(n):ee(n.items,n.base)}function pt(s){const e=[];let t=0;for(const n in s){const o=s[n];if(o.items){t=e.push(o);continue}e[t]||e.push({items:[]}),e[t].items.push(o)}return e}function ht(s){const e=[];function t(n){for(const o of n)o.text&&o.link&&e.push({text:o.text,link:o.link,docFooterText:o.docFooterText}),o.items&&t(o.items)}return t(s),e}function ce(s,e){return Array.isArray(e)?e.some(t=>ce(s,t)):U(s,e.link)?!0:e.items?ce(s,e.items):!1}function ee(s,e){return[...s].map(t=>{const n={...t},o=n.base||e;return o&&n.link&&(n.link=o+n.link),n.items&&(n.items=ee(n.items,o)),n})}function D(){const{frontmatter:s,page:e,theme:t}=P(),n=ie("(min-width: 960px)"),o=L(!1),r=y(()=>{const S=t.value.sidebar,b=e.value.relativePath;return S?Ie(S,b):[]}),d=L(r.value);R(r,(S,b)=>{JSON.stringify(S)!==JSON.stringify(b)&&(d.value=r.value)});const p=y(()=>s.value.sidebar!==!1&&d.value.length>0&&s.value.layout!=="home"),_=y(()=>k?s.value.aside==null?t.value.aside==="left":s.value.aside==="left":!1),k=y(()=>s.value.layout==="home"?!1:s.value.aside!=null?!!s.value.aside:t.value.aside!==!1),N=y(()=>p.value&&n.value),T=y(()=>p.value?pt(d.value):[]);function A(){o.value=!0}function I(){o.value=!1}function w(){o.value?I():A()}return{isOpen:o,sidebar:d,sidebarGroups:T,hasSidebar:p,hasAside:k,leftAside:_,isSidebarEnabled:N,open:A,close:I,toggle:w}}function ft(s,e){let t;se(()=>{t=s.value?document.activeElement:void 0}),F(()=>{window.addEventListener("keyup",n)}),J(()=>{window.removeEventListener("keyup",n)});function n(o){o.key==="Escape"&&s.value&&(e(),t==null||t.focus())}}const Te=L(q?location.hash:"");q&&window.addEventListener("hashchange",()=>{Te.value=location.hash});function mt(s){const{page:e}=P(),t=L(!1),n=y(()=>s.value.collapsed!=null),o=y(()=>!!s.value.link),r=L(!1),d=()=>{r.value=U(e.value.relativePath,s.value.link)};R([e,s,Te],d),F(d);const p=y(()=>r.value?!0:s.value.items?ce(e.value.relativePath,s.value.items):!1),_=y(()=>!!(s.value.items&&s.value.items.length));se(()=>{t.value=!!(n.value&&s.value.collapsed)}),we(()=>{(r.value||p.value)&&(t.value=!1)});function k(){n.value&&(t.value=!t.value)}return{collapsed:t,collapsible:n,isLink:o,isActiveLink:r,hasActiveLink:p,hasChildren:_,toggle:k}}function gt(){const{hasSidebar:s}=D(),e=ie("(min-width: 960px)"),t=ie("(min-width: 1280px)");return{isAsideEnabled:y(()=>!t.value&&!e.value?!1:s.value?t.value:e.value)}}const bt=71;function ve(s){return typeof s.outline=="object"&&!Array.isArray(s.outline)&&s.outline.label||s.outlineTitle||"On this page"}function pe(s){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const n=Number(t.tagName[1]);return{title:$t(t),link:"#"+t.id,level:n}});return kt(e,s)}function $t(s){let e="";for(const t of s.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function kt(s,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[n,o]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;s=s.filter(d=>d.level>=n&&d.level<=o);const r=[];e:for(let d=0;d=0;_--){const k=s[_];if(k.level{requestAnimationFrame(r),window.addEventListener("scroll",n)}),Oe(()=>{d(location.hash)}),J(()=>{window.removeEventListener("scroll",n)});function r(){if(!t.value)return;const p=[].slice.call(s.value.querySelectorAll(".outline-link")),_=[].slice.call(document.querySelectorAll(".content .header-anchor")).filter(I=>p.some(w=>w.hash===I.hash&&I.offsetParent!==null)),k=window.scrollY,N=window.innerHeight,T=document.body.offsetHeight,A=Math.abs(k+N-T)<1;if(_.length&&A){d(_[_.length-1].hash);return}for(let I=0;I<_.length;I++){const w=_[I],S=_[I+1],[b,x]=Pt(I,w,S);if(b){d(x);return}}}function d(p){o&&o.classList.remove("active"),p==null?o=null:o=s.value.querySelector(`a[href="${decodeURIComponent(p)}"]`);const _=o;_?(_.classList.add("active"),e.value.style.top=_.offsetTop+33+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function Pe(s){return s.parentElement.offsetTop-bt}function Pt(s,e,t){const n=window.scrollY;return s===0&&n===0?[!0,null]:n{const o=j("VPDocOutlineItem",!0);return a(),l("ul",{class:C(t.root?"root":"nested")},[(a(!0),l(M,null,B(t.headers,({children:r,link:d,title:p})=>(a(),l("li",null,[c("a",{class:"outline-link",href:d,onClick:e,title:p},V(p),9,Vt),r!=null&&r.length?(a(),$(o,{key:0,headers:r},null,8,["headers"])):f("",!0)]))),256))],2)}}});const he=g(wt,[["__scopeId","data-v-1772882b"]]),St=s=>(z("data-v-98b3e62f"),s=s(),E(),s),Lt={class:"content"},Mt={class:"outline-title",role:"heading","aria-level":"2"},Ct={"aria-labelledby":"doc-outline-aria-label"},Nt=St(()=>c("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),It=m({__name:"VPDocAsideOutline",setup(s){const{frontmatter:e,theme:t}=P(),n=_e([]);W(()=>{n.value=pe(e.value.outline??t.value.outline)});const o=L(),r=L();return yt(o,r),(d,p)=>(a(),l("div",{class:C(["VPDocAsideOutline",{"has-outline":n.value.length>0}]),ref_key:"container",ref:o,role:"navigation"},[c("div",Lt,[c("div",{class:"outline-marker",ref_key:"marker",ref:r},null,512),c("div",Mt,V(i(ve)(i(t))),1),c("nav",Ct,[Nt,h(he,{headers:n.value,root:!0},null,8,["headers"])])])],2))}});const Tt=g(It,[["__scopeId","data-v-98b3e62f"]]),Bt={class:"VPDocAsideCarbonAds"},At=m({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(s){const e=()=>null;return(t,n)=>(a(),l("div",Bt,[h(i(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),Ht=s=>(z("data-v-d3dab3d7"),s=s(),E(),s),xt={class:"VPDocAside"},zt=Ht(()=>c("div",{class:"spacer"},null,-1)),Et=m({__name:"VPDocAside",setup(s){const{theme:e}=P();return(t,n)=>(a(),l("div",xt,[u(t.$slots,"aside-top",{},void 0,!0),u(t.$slots,"aside-outline-before",{},void 0,!0),h(Tt),u(t.$slots,"aside-outline-after",{},void 0,!0),zt,u(t.$slots,"aside-ads-before",{},void 0,!0),i(e).carbonAds?(a(),$(At,{key:0,"carbon-ads":i(e).carbonAds},null,8,["carbon-ads"])):f("",!0),u(t.$slots,"aside-ads-after",{},void 0,!0),u(t.$slots,"aside-bottom",{},void 0,!0)]))}});const Dt=g(Et,[["__scopeId","data-v-d3dab3d7"]]);function Ft(){const{theme:s,page:e}=P();return y(()=>{const{text:t="Edit this page",pattern:n=""}=s.value.editLink||{};let o;return typeof n=="function"?o=n(e.value):o=n.replace(/:path/g,e.value.filePath),{url:o,text:t}})}function Ot(){const{page:s,theme:e,frontmatter:t}=P();return y(()=>{var _,k,N,T,A,I,w,S;const n=Ie(e.value.sidebar,s.value.relativePath),o=ht(n),r=o.findIndex(b=>U(s.value.relativePath,b.link)),d=((_=e.value.docFooter)==null?void 0:_.prev)===!1&&!t.value.prev||t.value.prev===!1,p=((k=e.value.docFooter)==null?void 0:k.next)===!1&&!t.value.next||t.value.next===!1;return{prev:d?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((N=o[r-1])==null?void 0:N.docFooterText)??((T=o[r-1])==null?void 0:T.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((A=o[r-1])==null?void 0:A.link)},next:p?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((I=o[r+1])==null?void 0:I.docFooterText)??((w=o[r+1])==null?void 0:w.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((S=o[r+1])==null?void 0:S.link)}}})}const Gt={},Ut={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Rt=c("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),jt=c("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),qt=[Rt,jt];function Kt(s,e){return a(),l("svg",Ut,qt)}const Wt=g(Gt,[["render",Kt]]),O=m({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(s){const e=s,t=y(()=>e.tag??(e.href?"a":"span")),n=y(()=>e.href&&Se.test(e.href));return(o,r)=>(a(),$(G(t.value),{class:C(["VPLink",{link:o.href,"vp-external-link-icon":n.value,"no-icon":o.noIcon}]),href:o.href?i(Y)(o.href):void 0,target:o.target??(n.value?"_blank":void 0),rel:o.rel??(n.value?"noreferrer":void 0)},{default:v(()=>[u(o.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),Yt={class:"VPLastUpdated"},Jt=["datetime"],Xt=m({__name:"VPDocFooterLastUpdated",setup(s){const{theme:e,page:t,frontmatter:n,lang:o}=P(),r=y(()=>new Date(n.value.lastUpdated??t.value.lastUpdated)),d=y(()=>r.value.toISOString()),p=L("");return F(()=>{se(()=>{var _,k,N;p.value=new Intl.DateTimeFormat((k=(_=e.value.lastUpdated)==null?void 0:_.formatOptions)!=null&&k.forceLocale?o.value:void 0,((N=e.value.lastUpdated)==null?void 0:N.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(r.value)})}),(_,k)=>{var N;return a(),l("p",Yt,[H(V(((N=i(e).lastUpdated)==null?void 0:N.text)||i(e).lastUpdatedText||"Last updated")+": ",1),c("time",{datetime:d.value},V(p.value),9,Jt)])}}});const Zt=g(Xt,[["__scopeId","data-v-43ed3de5"]]),Qt={key:0,class:"VPDocFooter"},es={key:0,class:"edit-info"},ts={key:0,class:"edit-link"},ss={key:1,class:"last-updated"},ns={key:1,class:"prev-next"},os={class:"pager"},as=["href"],rs=["innerHTML"],is=["innerHTML"],ls={class:"pager"},cs=["href"],us=["innerHTML"],ds=["innerHTML"],_s=m({__name:"VPDocFooter",setup(s){const{theme:e,page:t,frontmatter:n}=P(),o=Ft(),r=Ot(),d=y(()=>e.value.editLink&&n.value.editLink!==!1),p=y(()=>t.value.lastUpdated&&n.value.lastUpdated!==!1),_=y(()=>d.value||p.value||r.value.prev||r.value.next);return(k,N)=>{var T,A,I,w,S,b;return _.value?(a(),l("footer",Qt,[u(k.$slots,"doc-footer-before",{},void 0,!0),d.value||p.value?(a(),l("div",es,[d.value?(a(),l("div",ts,[h(O,{class:"edit-link-button",href:i(o).url,"no-icon":!0},{default:v(()=>[h(Wt,{class:"edit-link-icon","aria-label":"edit icon"}),H(" "+V(i(o).text),1)]),_:1},8,["href"])])):f("",!0),p.value?(a(),l("div",ss,[h(Zt)])):f("",!0)])):f("",!0),(T=i(r).prev)!=null&&T.link||(A=i(r).next)!=null&&A.link?(a(),l("nav",ns,[c("div",os,[(I=i(r).prev)!=null&&I.link?(a(),l("a",{key:0,class:"pager-link prev",href:i(Y)(i(r).prev.link)},[c("span",{class:"desc",innerHTML:((w=i(e).docFooter)==null?void 0:w.prev)||"Previous page"},null,8,rs),c("span",{class:"title",innerHTML:i(r).prev.text},null,8,is)],8,as)):f("",!0)]),c("div",ls,[(S=i(r).next)!=null&&S.link?(a(),l("a",{key:0,class:"pager-link next",href:i(Y)(i(r).next.link)},[c("span",{class:"desc",innerHTML:((b=i(e).docFooter)==null?void 0:b.next)||"Next page"},null,8,us),c("span",{class:"title",innerHTML:i(r).next.text},null,8,ds)],8,cs)):f("",!0)])])):f("",!0)])):f("",!0)}}});const vs=g(_s,[["__scopeId","data-v-d801cd4d"]]),ps={},hs={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},fs=c("path",{d:"M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"},null,-1),ms=[fs];function gs(s,e){return a(),l("svg",hs,ms)}const fe=g(ps,[["render",gs]]),bs={key:0,class:"VPDocOutlineDropdown"},$s={key:0,class:"items"},ks=m({__name:"VPDocOutlineDropdown",setup(s){const{frontmatter:e,theme:t}=P(),n=L(!1);W(()=>{n.value=!1});const o=_e([]);return W(()=>{o.value=pe(e.value.outline??t.value.outline)}),(r,d)=>o.value.length>0?(a(),l("div",bs,[c("button",{onClick:d[0]||(d[0]=p=>n.value=!n.value),class:C({open:n.value})},[H(V(i(ve)(i(t)))+" ",1),h(fe,{class:"icon"})],2),n.value?(a(),l("div",$s,[h(he,{headers:o.value},null,8,["headers"])])):f("",!0)])):f("",!0)}});const ys=g(ks,[["__scopeId","data-v-3351e765"]]),Ps=s=>(z("data-v-eb54b406"),s=s(),E(),s),Vs={class:"container"},ws=Ps(()=>c("div",{class:"aside-curtain"},null,-1)),Ss={class:"aside-container"},Ls={class:"aside-content"},Ms={class:"content"},Cs={class:"content-container"},Ns={class:"main"},Is=m({__name:"VPDoc",setup(s){const{theme:e}=P(),t=ne(),{hasSidebar:n,hasAside:o,leftAside:r}=D(),d=y(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(p,_)=>{const k=j("Content");return a(),l("div",{class:C(["VPDoc",{"has-sidebar":i(n),"has-aside":i(o)}])},[u(p.$slots,"doc-top",{},void 0,!0),c("div",Vs,[i(o)?(a(),l("div",{key:0,class:C(["aside",{"left-aside":i(r)}])},[ws,c("div",Ss,[c("div",Ls,[h(Dt,null,{"aside-top":v(()=>[u(p.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[u(p.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[u(p.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[u(p.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[u(p.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[u(p.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):f("",!0),c("div",Ms,[c("div",Cs,[u(p.$slots,"doc-before",{},void 0,!0),h(ys),c("main",Ns,[h(k,{class:C(["vp-doc",[d.value,i(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),h(vs,null,{"doc-footer-before":v(()=>[u(p.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),u(p.$slots,"doc-after",{},void 0,!0)])])]),u(p.$slots,"doc-bottom",{},void 0,!0)],2)}}});const Ts=g(Is,[["__scopeId","data-v-eb54b406"]]),Bs=m({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{}},setup(s){const e=s,t=y(()=>e.href&&Se.test(e.href)),n=y(()=>e.tag||e.href?"a":"button");return(o,r)=>(a(),$(G(n.value),{class:C(["VPButton",[o.size,o.theme]]),href:o.href?i(Y)(o.href):void 0,target:t.value?"_blank":void 0,rel:t.value?"noreferrer":void 0},{default:v(()=>[H(V(o.text),1)]),_:1},8,["class","href","target","rel"]))}});const As=g(Bs,[["__scopeId","data-v-a86ee6f3"]]),Hs=["src","alt"],xs=m({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(s){return(e,t)=>{const n=j("VPImage",!0);return e.image?(a(),l(M,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),l("img",Q({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:i(de)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,Hs)):(a(),l(M,{key:1},[h(n,Q({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),h(n,Q({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):f("",!0)}}});const te=g(xs,[["__scopeId","data-v-26d78c9a"]]),zs=s=>(z("data-v-b88480c1"),s=s(),E(),s),Es={class:"container"},Ds={class:"main"},Fs={key:0,class:"name"},Os=["innerHTML"],Gs=["innerHTML"],Us=["innerHTML"],Rs={key:0,class:"actions"},js={key:0,class:"image"},qs={class:"image-container"},Ks=zs(()=>c("div",{class:"image-bg"},null,-1)),Ws=m({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(s){const e=oe("hero-image-slot-exists");return(t,n)=>(a(),l("div",{class:C(["VPHero",{"has-image":t.image||i(e)}])},[c("div",Es,[c("div",Ds,[u(t.$slots,"home-hero-info",{},()=>[t.name?(a(),l("h1",Fs,[c("span",{innerHTML:t.name,class:"clip"},null,8,Os)])):f("",!0),t.text?(a(),l("p",{key:1,innerHTML:t.text,class:"text"},null,8,Gs)):f("",!0),t.tagline?(a(),l("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,Us)):f("",!0)],!0),t.actions?(a(),l("div",Rs,[(a(!0),l(M,null,B(t.actions,o=>(a(),l("div",{key:o.link,class:"action"},[h(As,{tag:"a",size:"medium",theme:o.theme,text:o.text,href:o.link},null,8,["theme","text","href"])]))),128))])):f("",!0)]),t.image||i(e)?(a(),l("div",js,[c("div",qs,[Ks,u(t.$slots,"home-hero-image",{},()=>[t.image?(a(),$(te,{key:0,class:"image-src",image:t.image},null,8,["image"])):f("",!0)],!0)])])):f("",!0)])],2))}});const Ys=g(Ws,[["__scopeId","data-v-b88480c1"]]),Js=m({__name:"VPHomeHero",setup(s){const{frontmatter:e}=P();return(t,n)=>i(e).hero?(a(),$(Ys,{key:0,class:"VPHomeHero",name:i(e).hero.name,text:i(e).hero.text,tagline:i(e).hero.tagline,image:i(e).hero.image,actions:i(e).hero.actions},{"home-hero-info":v(()=>[u(t.$slots,"home-hero-info")]),"home-hero-image":v(()=>[u(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):f("",!0)}}),Xs={},Zs={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Qs=c("path",{d:"M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"},null,-1),en=[Qs];function tn(s,e){return a(),l("svg",Zs,en)}const sn=g(Xs,[["render",tn]]),nn={class:"box"},on={key:0,class:"icon"},an=["innerHTML"],rn=["innerHTML"],ln=["innerHTML"],cn={key:4,class:"link-text"},un={class:"link-text-value"},dn=m({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(s){return(e,t)=>(a(),$(O,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:v(()=>[c("article",nn,[typeof e.icon=="object"&&e.icon.wrap?(a(),l("div",on,[h(te,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(a(),$(te,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(a(),l("div",{key:2,class:"icon",innerHTML:e.icon},null,8,an)):f("",!0),c("h2",{class:"title",innerHTML:e.title},null,8,rn),e.details?(a(),l("p",{key:3,class:"details",innerHTML:e.details},null,8,ln)):f("",!0),e.linkText?(a(),l("div",cn,[c("p",un,[H(V(e.linkText)+" ",1),h(sn,{class:"link-text-icon"})])])):f("",!0)])]),_:1},8,["href","rel","target","tag"]))}});const _n=g(dn,[["__scopeId","data-v-ec7504fd"]]),vn={key:0,class:"VPFeatures"},pn={class:"container"},hn={class:"items"},fn=m({__name:"VPFeatures",props:{features:{}},setup(s){const e=s,t=y(()=>{const n=e.features.length;if(n){if(n===2)return"grid-2";if(n===3)return"grid-3";if(n%3===0)return"grid-6";if(n>3)return"grid-4"}else return});return(n,o)=>n.features?(a(),l("div",vn,[c("div",pn,[c("div",hn,[(a(!0),l(M,null,B(n.features,r=>(a(),l("div",{key:r.title,class:C(["item",[t.value]])},[h(_n,{icon:r.icon,title:r.title,details:r.details,link:r.link,"link-text":r.linkText,rel:r.rel,target:r.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):f("",!0)}});const mn=g(fn,[["__scopeId","data-v-4746fcfd"]]),gn=m({__name:"VPHomeFeatures",setup(s){const{frontmatter:e}=P();return(t,n)=>i(e).features?(a(),$(mn,{key:0,class:"VPHomeFeatures",features:i(e).features},null,8,["features"])):f("",!0)}}),bn={class:"VPHome"},$n=m({__name:"VPHome",setup(s){return(e,t)=>{const n=j("Content");return a(),l("div",bn,[u(e.$slots,"home-hero-before",{},void 0,!0),h(Js,null,{"home-hero-info":v(()=>[u(e.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[u(e.$slots,"home-hero-image",{},void 0,!0)]),_:3}),u(e.$slots,"home-hero-after",{},void 0,!0),u(e.$slots,"home-features-before",{},void 0,!0),h(gn),u(e.$slots,"home-features-after",{},void 0,!0),h(n)])}}});const kn=g($n,[["__scopeId","data-v-f599c3dc"]]),yn={},Pn={class:"VPPage"};function Vn(s,e){const t=j("Content");return a(),l("div",Pn,[u(s.$slots,"page-top"),h(t),u(s.$slots,"page-bottom")])}const wn=g(yn,[["render",Vn]]),Sn=m({__name:"VPContent",setup(s){const{page:e,frontmatter:t}=P(),{hasSidebar:n}=D();return(o,r)=>(a(),l("div",{class:C(["VPContent",{"has-sidebar":i(n),"is-home":i(t).layout==="home"}]),id:"VPContent"},[i(e).isNotFound?u(o.$slots,"not-found",{key:0},()=>[h(vt)],!0):i(t).layout==="page"?(a(),$(wn,{key:1},{"page-top":v(()=>[u(o.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[u(o.$slots,"page-bottom",{},void 0,!0)]),_:3})):i(t).layout==="home"?(a(),$(kn,{key:2},{"home-hero-before":v(()=>[u(o.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[u(o.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[u(o.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[u(o.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[u(o.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[u(o.$slots,"home-features-after",{},void 0,!0)]),_:3})):i(t).layout&&i(t).layout!=="doc"?(a(),$(G(i(t).layout),{key:3})):(a(),$(Ts,{key:4},{"doc-top":v(()=>[u(o.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[u(o.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":v(()=>[u(o.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[u(o.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[u(o.$slots,"doc-after",{},void 0,!0)]),"aside-top":v(()=>[u(o.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":v(()=>[u(o.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[u(o.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[u(o.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[u(o.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":v(()=>[u(o.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}});const Ln=g(Sn,[["__scopeId","data-v-7787f055"]]),Mn={class:"container"},Cn=["innerHTML"],Nn=["innerHTML"],In=m({__name:"VPFooter",setup(s){const{theme:e,frontmatter:t}=P(),{hasSidebar:n}=D();return(o,r)=>i(e).footer&&i(t).footer!==!1?(a(),l("footer",{key:0,class:C(["VPFooter",{"has-sidebar":i(n)}])},[c("div",Mn,[i(e).footer.message?(a(),l("p",{key:0,class:"message",innerHTML:i(e).footer.message},null,8,Cn)):f("",!0),i(e).footer.copyright?(a(),l("p",{key:1,class:"copyright",innerHTML:i(e).footer.copyright},null,8,Nn)):f("",!0)])],2)):f("",!0)}});const Tn=g(In,[["__scopeId","data-v-855b7db4"]]),Bn={class:"header"},An={class:"outline"},Hn=m({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(s){const e=s,{theme:t}=P(),n=L(!1),o=L(0),r=L();W(()=>{n.value=!1});function d(){n.value=!n.value,o.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function p(k){k.target.classList.contains("outline-link")&&(r.value&&(r.value.style.transition="none"),Ue(()=>{n.value=!1}))}function _(){n.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(k,N)=>(a(),l("div",{class:"VPLocalNavOutlineDropdown",style:Ge({"--vp-vh":o.value+"px"})},[k.headers.length>0?(a(),l("button",{key:0,onClick:d,class:C({open:n.value})},[H(V(i(ve)(i(t)))+" ",1),h(fe,{class:"icon"})],2)):(a(),l("button",{key:1,onClick:_},V(i(t).returnToTopLabel||"Return to top"),1)),h(ue,{name:"flyout"},{default:v(()=>[n.value?(a(),l("div",{key:0,ref_key:"items",ref:r,class:"items",onClick:p},[c("div",Bn,[c("a",{class:"top-link",href:"#",onClick:_},V(i(t).returnToTopLabel||"Return to top"),1)]),c("div",An,[h(he,{headers:k.headers},null,8,["headers"])])],512)):f("",!0)]),_:1})],4))}});const xn=g(Hn,[["__scopeId","data-v-55e6f1d6"]]),zn={},En={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Dn=c("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),Fn=c("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),On=c("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),Gn=c("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),Un=[Dn,Fn,On,Gn];function Rn(s,e){return a(),l("svg",En,Un)}const jn=g(zn,[["render",Rn]]),qn=["aria-expanded"],Kn={class:"menu-text"},Wn=m({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(s){const{theme:e,frontmatter:t}=P(),{hasSidebar:n}=D(),{y:o}=Le(),r=_e([]),d=L(0);F(()=>{d.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),W(()=>{r.value=pe(t.value.outline??e.value.outline)});const p=y(()=>r.value.length===0&&!n.value),_=y(()=>({VPLocalNav:!0,fixed:p.value,"reached-top":o.value>=d.value}));return(k,N)=>i(t).layout!=="home"&&(!p.value||i(o)>=d.value)?(a(),l("div",{key:0,class:C(_.value)},[i(n)?(a(),l("button",{key:0,class:"menu","aria-expanded":k.open,"aria-controls":"VPSidebarNav",onClick:N[0]||(N[0]=T=>k.$emit("open-menu"))},[h(jn,{class:"menu-icon"}),c("span",Kn,V(i(e).sidebarMenuLabel||"Menu"),1)],8,qn)):f("",!0),h(xn,{headers:r.value,navHeight:d.value},null,8,["headers","navHeight"])],2)):f("",!0)}});const Yn=g(Wn,[["__scopeId","data-v-6e4e13c1"]]);function Jn(){const s=L(!1);function e(){s.value=!0,window.addEventListener("resize",o)}function t(){s.value=!1,window.removeEventListener("resize",o)}function n(){s.value?t():e()}function o(){window.outerWidth>=768&&t()}const r=ne();return R(()=>r.path,t),{isScreenOpen:s,openScreen:e,closeScreen:t,toggleScreen:n}}const Xn={},Zn={class:"VPSwitch",type:"button",role:"switch"},Qn={class:"check"},eo={key:0,class:"icon"};function to(s,e){return a(),l("button",Zn,[c("span",Qn,[s.$slots.default?(a(),l("span",eo,[u(s.$slots,"default",{},void 0,!0)])):f("",!0)])])}const so=g(Xn,[["render",to],["__scopeId","data-v-ad8fa6cf"]]),no={},oo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ao=c("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),ro=[ao];function io(s,e){return a(),l("svg",oo,ro)}const lo=g(no,[["render",io]]),co={},uo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},_o=Re('',9),vo=[_o];function po(s,e){return a(),l("svg",uo,vo)}const ho=g(co,[["render",po]]),fo=m({__name:"VPSwitchAppearance",setup(s){const{isDark:e}=P(),t=oe("toggle-appearance",()=>{e.value=!e.value});return(n,o)=>(a(),$(so,{title:"toggle dark mode",class:"VPSwitchAppearance","aria-checked":i(e),onClick:i(t)},{default:v(()=>[h(ho,{class:"sun"}),h(lo,{class:"moon"})]),_:1},8,["aria-checked","onClick"]))}});const me=g(fo,[["__scopeId","data-v-f31c77b6"]]),mo={key:0,class:"VPNavBarAppearance"},go=m({__name:"VPNavBarAppearance",setup(s){const{site:e}=P();return(t,n)=>i(e).appearance&&i(e).appearance!=="force-dark"?(a(),l("div",mo,[h(me)])):f("",!0)}});const bo=g(go,[["__scopeId","data-v-82003167"]]),ge=L();let Be=!1,re=0;function $o(s){const e=L(!1);if(q){!Be&&ko(),re++;const t=R(ge,n=>{var o,r,d;n===s.el.value||(o=s.el.value)!=null&&o.contains(n)?(e.value=!0,(r=s.onFocus)==null||r.call(s)):(e.value=!1,(d=s.onBlur)==null||d.call(s))});J(()=>{t(),re--,re||yo()})}return je(e)}function ko(){document.addEventListener("focusin",Ae),Be=!0,ge.value=document.activeElement}function yo(){document.removeEventListener("focusin",Ae)}function Ae(){ge.value=document.activeElement}const Po={},Vo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},wo=c("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),So=[wo];function Lo(s,e){return a(),l("svg",Vo,So)}const He=g(Po,[["render",Lo]]),Mo={},Co={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},No=c("circle",{cx:"12",cy:"12",r:"2"},null,-1),Io=c("circle",{cx:"19",cy:"12",r:"2"},null,-1),To=c("circle",{cx:"5",cy:"12",r:"2"},null,-1),Bo=[No,Io,To];function Ao(s,e){return a(),l("svg",Co,Bo)}const Ho=g(Mo,[["render",Ao]]),xo={class:"VPMenuLink"},zo=m({__name:"VPMenuLink",props:{item:{}},setup(s){const{page:e}=P();return(t,n)=>(a(),l("div",xo,[h(O,{class:C({active:i(U)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:v(()=>[H(V(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}});const ae=g(zo,[["__scopeId","data-v-df1d8bd6"]]),Eo={class:"VPMenuGroup"},Do={key:0,class:"title"},Fo=m({__name:"VPMenuGroup",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),l("div",Eo,[e.text?(a(),l("p",Do,V(e.text),1)):f("",!0),(a(!0),l(M,null,B(e.items,n=>(a(),l(M,null,["link"in n?(a(),$(ae,{key:0,item:n},null,8,["item"])):f("",!0)],64))),256))]))}});const Oo=g(Fo,[["__scopeId","data-v-bdc27f57"]]),Go={class:"VPMenu"},Uo={key:0,class:"items"},Ro=m({__name:"VPMenu",props:{items:{}},setup(s){return(e,t)=>(a(),l("div",Go,[e.items?(a(),l("div",Uo,[(a(!0),l(M,null,B(e.items,n=>(a(),l(M,{key:n.text},["link"in n?(a(),$(ae,{key:0,item:n},null,8,["item"])):(a(),$(Oo,{key:1,text:n.text,items:n.items},null,8,["text","items"]))],64))),128))])):f("",!0),u(e.$slots,"default",{},void 0,!0)]))}});const jo=g(Ro,[["__scopeId","data-v-3795579e"]]),qo=["aria-expanded","aria-label"],Ko={key:0,class:"text"},Wo=["innerHTML"],Yo={class:"menu"},Jo=m({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(s){const e=L(!1),t=L();$o({el:t,onBlur:n});function n(){e.value=!1}return(o,r)=>(a(),l("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:r[1]||(r[1]=d=>e.value=!0),onMouseleave:r[2]||(r[2]=d=>e.value=!1)},[c("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":o.label,onClick:r[0]||(r[0]=d=>e.value=!e.value)},[o.button||o.icon?(a(),l("span",Ko,[o.icon?(a(),$(G(o.icon),{key:0,class:"option-icon"})):f("",!0),o.button?(a(),l("span",{key:1,innerHTML:o.button},null,8,Wo)):f("",!0),h(He,{class:"text-icon"})])):(a(),$(Ho,{key:1,class:"icon"}))],8,qo),c("div",Yo,[h(jo,{items:o.items},{default:v(()=>[u(o.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}});const be=g(Jo,[["__scopeId","data-v-419e6f76"]]),Xo={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',mastodon:'Mastodon',slack:'Slack',twitter:'Twitter',x:'X',youtube:'YouTube'},Zo=["href","aria-label","innerHTML"],Qo=m({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(s){const e=s,t=y(()=>typeof e.icon=="object"?e.icon.svg:Xo[e.icon]);return(n,o)=>(a(),l("a",{class:"VPSocialLink no-icon",href:n.link,"aria-label":n.ariaLabel??(typeof n.icon=="string"?n.icon:""),target:"_blank",rel:"noopener",innerHTML:t.value},null,8,Zo))}});const ea=g(Qo,[["__scopeId","data-v-d53a05fb"]]),ta={class:"VPSocialLinks"},sa=m({__name:"VPSocialLinks",props:{links:{}},setup(s){return(e,t)=>(a(),l("div",ta,[(a(!0),l(M,null,B(e.links,({link:n,icon:o,ariaLabel:r})=>(a(),$(ea,{key:n,icon:o,link:n,ariaLabel:r},null,8,["icon","link","ariaLabel"]))),128))]))}});const $e=g(sa,[["__scopeId","data-v-aea42604"]]),na={key:0,class:"group translations"},oa={class:"trans-title"},aa={key:1,class:"group"},ra={class:"item appearance"},ia={class:"label"},la={class:"appearance-action"},ca={key:2,class:"group"},ua={class:"item social-links"},da=m({__name:"VPNavBarExtra",setup(s){const{site:e,theme:t}=P(),{localeLinks:n,currentLang:o}=X({correspondingLink:!0}),r=y(()=>n.value.length&&o.value.label||e.value.appearance||t.value.socialLinks);return(d,p)=>r.value?(a(),$(be,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:v(()=>[i(n).length&&i(o).label?(a(),l("div",na,[c("p",oa,V(i(o).label),1),(a(!0),l(M,null,B(i(n),_=>(a(),$(ae,{key:_.link,item:_},null,8,["item"]))),128))])):f("",!0),i(e).appearance?(a(),l("div",aa,[c("div",ra,[c("p",ia,V(i(t).darkModeSwitchLabel||"Appearance"),1),c("div",la,[h(me)])])])):f("",!0),i(t).socialLinks?(a(),l("div",ca,[c("div",ua,[h($e,{class:"social-links-list",links:i(t).socialLinks},null,8,["links"])])])):f("",!0)]),_:1})):f("",!0)}});const _a=g(da,[["__scopeId","data-v-edb32f2a"]]),va=s=>(z("data-v-305e35d4"),s=s(),E(),s),pa=["aria-expanded"],ha=va(()=>c("span",{class:"container"},[c("span",{class:"top"}),c("span",{class:"middle"}),c("span",{class:"bottom"})],-1)),fa=[ha],ma=m({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(s){return(e,t)=>(a(),l("button",{type:"button",class:C(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=n=>e.$emit("click"))},fa,10,pa))}});const ga=g(ma,[["__scopeId","data-v-305e35d4"]]),ba=["innerHTML"],$a=m({__name:"VPNavBarMenuLink",props:{item:{}},setup(s){const{page:e}=P();return(t,n)=>(a(),$(O,{class:C({VPNavBarMenuLink:!0,active:i(U)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:v(()=>[c("span",{innerHTML:t.item.text},null,8,ba)]),_:1},8,["class","href","target","rel"]))}});const ka=g($a,[["__scopeId","data-v-0eb8cc79"]]),ya=m({__name:"VPNavBarMenuGroup",props:{item:{}},setup(s){const e=s,{page:t}=P(),n=r=>"link"in r?U(t.value.relativePath,r.link,!!e.item.activeMatch):r.items.some(n),o=y(()=>n(e.item));return(r,d)=>(a(),$(be,{class:C({VPNavBarMenuGroup:!0,active:i(U)(i(t).relativePath,r.item.activeMatch,!!r.item.activeMatch)||o.value}),button:r.item.text,items:r.item.items},null,8,["class","button","items"]))}}),Pa=s=>(z("data-v-368cfbc9"),s=s(),E(),s),Va={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},wa=Pa(()=>c("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Sa=m({__name:"VPNavBarMenu",setup(s){const{theme:e}=P();return(t,n)=>i(e).nav?(a(),l("nav",Va,[wa,(a(!0),l(M,null,B(i(e).nav,o=>(a(),l(M,{key:o.text},["link"in o?(a(),$(ka,{key:0,item:o},null,8,["item"])):(a(),$(ya,{key:1,item:o},null,8,["item"]))],64))),128))])):f("",!0)}});const La=g(Sa,[["__scopeId","data-v-368cfbc9"]]);const Ma={type:"button",class:"DocSearch DocSearch-Button","aria-label":"Search"},Ca={class:"DocSearch-Button-Container"},Na=c("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20","aria-label":"search icon"},[c("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Ia={class:"DocSearch-Button-Placeholder"},Ta=c("span",{class:"DocSearch-Button-Keys"},[c("kbd",{class:"DocSearch-Button-Key"}),c("kbd",{class:"DocSearch-Button-Key"},"K")],-1),Ve=m({__name:"VPNavBarSearchButton",props:{placeholder:{}},setup(s){return(e,t)=>(a(),l("button",Ma,[c("span",Ca,[Na,c("span",Ia,V(e.placeholder),1)]),Ta]))}});const Ba={class:"VPNavBarSearch"},Aa={id:"local-search"},Ha={key:1,id:"docsearch"},xa=m({__name:"VPNavBarSearch",setup(s){const e=()=>null,t=qe(()=>Ke(()=>import("./VPAlgoliaSearchBox.a4c0242a.js"),["assets/chunks/VPAlgoliaSearchBox.a4c0242a.js","assets/chunks/framework.b7580407.js"])),{theme:n,localeIndex:o}=P(),r=L(!1),d=L(!1),p=y(()=>{var S,b,x,Z,K,ke,ye;const w=((S=n.value.search)==null?void 0:S.options)??n.value.algolia;return((K=(Z=(x=(b=w==null?void 0:w.locales)==null?void 0:b[o.value])==null?void 0:x.translations)==null?void 0:Z.button)==null?void 0:K.buttonText)||((ye=(ke=w==null?void 0:w.translations)==null?void 0:ke.button)==null?void 0:ye.buttonText)||"Search"}),_=()=>{const w="VPAlgoliaPreconnect";(window.requestIdleCallback||setTimeout)(()=>{var x;const b=document.createElement("link");b.id=w,b.rel="preconnect",b.href=`https://${(((x=n.value.search)==null?void 0:x.options)??n.value.algolia).appId}-dsn.algolia.net`,b.crossOrigin="",document.head.appendChild(b)})};F(()=>{_();const w=b=>{(b.key.toLowerCase()==="k"&&(b.metaKey||b.ctrlKey)||!T(b)&&b.key==="/")&&(b.preventDefault(),k(),S())},S=()=>{window.removeEventListener("keydown",w)};window.addEventListener("keydown",w),J(S)});function k(){r.value||(r.value=!0,setTimeout(N,16))}function N(){const w=new Event("keydown");w.key="k",w.metaKey=!0,window.dispatchEvent(w),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||N()},16)}function T(w){const S=w.target,b=S.tagName;return S.isContentEditable||b==="INPUT"||b==="SELECT"||b==="TEXTAREA"}const A=L(!1),I="algolia";return(w,S)=>{var b;return a(),l("div",Ba,[i(I)==="local"?(a(),l(M,{key:0},[A.value?(a(),$(i(e),{key:0,placeholder:p.value,onClose:S[0]||(S[0]=x=>A.value=!1)},null,8,["placeholder"])):f("",!0),c("div",Aa,[h(Ve,{placeholder:p.value,onClick:S[1]||(S[1]=x=>A.value=!0)},null,8,["placeholder"])])],64)):i(I)==="algolia"?(a(),l(M,{key:1},[r.value?(a(),$(i(t),{key:0,algolia:((b=i(n).search)==null?void 0:b.options)??i(n).algolia,onVnodeBeforeMount:S[2]||(S[2]=x=>d.value=!0)},null,8,["algolia"])):f("",!0),d.value?f("",!0):(a(),l("div",Ha,[h(Ve,{placeholder:p.value,onClick:k},null,8,["placeholder"])]))],64)):f("",!0)])}}});const za=m({__name:"VPNavBarSocialLinks",setup(s){const{theme:e}=P();return(t,n)=>i(e).socialLinks?(a(),$($e,{key:0,class:"VPNavBarSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}});const Ea=g(za,[["__scopeId","data-v-3c6c0985"]]),Da=["href"],Fa=m({__name:"VPNavBarTitle",setup(s){const{site:e,theme:t}=P(),{hasSidebar:n}=D(),{currentLang:o}=X();return(r,d)=>(a(),l("div",{class:C(["VPNavBarTitle",{"has-sidebar":i(n)}])},[c("a",{class:"title",href:i(t).logoLink??i(Y)(i(o).link)},[u(r.$slots,"nav-bar-title-before",{},void 0,!0),i(t).logo?(a(),$(te,{key:0,class:"logo",image:i(t).logo},null,8,["image"])):f("",!0),i(t).siteTitle?(a(),l(M,{key:1},[H(V(i(t).siteTitle),1)],64)):i(t).siteTitle===void 0?(a(),l(M,{key:2},[H(V(i(e).title),1)],64)):f("",!0),u(r.$slots,"nav-bar-title-after",{},void 0,!0)],8,Da)],2))}});const Oa=g(Fa,[["__scopeId","data-v-d919d4a8"]]),Ga={},Ua={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Ra=c("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),ja=c("path",{d:" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z ",class:"css-c4d79v"},null,-1),qa=[Ra,ja];function Ka(s,e){return a(),l("svg",Ua,qa)}const xe=g(Ga,[["render",Ka]]),Wa={class:"items"},Ya={class:"title"},Ja=m({__name:"VPNavBarTranslations",setup(s){const{theme:e}=P(),{localeLinks:t,currentLang:n}=X({correspondingLink:!0});return(o,r)=>i(t).length&&i(n).label?(a(),$(be,{key:0,class:"VPNavBarTranslations",icon:xe,label:i(e).langMenuLabel||"Change language"},{default:v(()=>[c("div",Wa,[c("p",Ya,V(i(n).label),1),(a(!0),l(M,null,B(i(t),d=>(a(),$(ae,{key:d.link,item:d},null,8,["item"]))),128))])]),_:1},8,["label"])):f("",!0)}});const Xa=g(Ja,[["__scopeId","data-v-780fc638"]]),Za=s=>(z("data-v-e4fc9f8b"),s=s(),E(),s),Qa={class:"container"},er={class:"title"},tr={class:"content"},sr=Za(()=>c("div",{class:"curtain"},null,-1)),nr={class:"content-body"},or=m({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(s){const{y:e}=Le(),{hasSidebar:t}=D(),{frontmatter:n}=P(),o=L({});return we(()=>{o.value={"has-sidebar":t.value,top:n.value.layout==="home"&&e.value===0}}),(r,d)=>(a(),l("div",{class:C(["VPNavBar",o.value])},[c("div",Qa,[c("div",er,[h(Oa,null,{"nav-bar-title-before":v(()=>[u(r.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[u(r.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),c("div",tr,[sr,c("div",nr,[u(r.$slots,"nav-bar-content-before",{},void 0,!0),h(xa,{class:"search"}),h(La,{class:"menu"}),h(Xa,{class:"translations"}),h(bo,{class:"appearance"}),h(Ea,{class:"social-links"}),h(_a,{class:"extra"}),u(r.$slots,"nav-bar-content-after",{},void 0,!0),h(ga,{class:"hamburger",active:r.isScreenOpen,onClick:d[0]||(d[0]=p=>r.$emit("toggle-screen"))},null,8,["active"])])])])],2))}});const ar=g(or,[["__scopeId","data-v-e4fc9f8b"]]),rr={key:0,class:"VPNavScreenAppearance"},ir={class:"text"},lr=m({__name:"VPNavScreenAppearance",setup(s){const{site:e,theme:t}=P();return(n,o)=>i(e).appearance?(a(),l("div",rr,[c("p",ir,V(i(t).darkModeSwitchLabel||"Appearance"),1),h(me)])):f("",!0)}});const cr=g(lr,[["__scopeId","data-v-14d6533b"]]),ur=m({__name:"VPNavScreenMenuLink",props:{item:{}},setup(s){const e=oe("close-screen");return(t,n)=>(a(),$(O,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:v(()=>[H(V(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const dr=g(ur,[["__scopeId","data-v-100771e7"]]),_r={},vr={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},pr=c("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),hr=[pr];function fr(s,e){return a(),l("svg",vr,hr)}const mr=g(_r,[["render",fr]]),gr=m({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(s){const e=oe("close-screen");return(t,n)=>(a(),$(O,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:v(()=>[H(V(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const ze=g(gr,[["__scopeId","data-v-bb6df54f"]]),br={class:"VPNavScreenMenuGroupSection"},$r={key:0,class:"title"},kr=m({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),l("div",br,[e.text?(a(),l("p",$r,V(e.text),1)):f("",!0),(a(!0),l(M,null,B(e.items,n=>(a(),$(ze,{key:n.text,item:n},null,8,["item"]))),128))]))}});const yr=g(kr,[["__scopeId","data-v-c3cb64a0"]]),Pr=["aria-controls","aria-expanded"],Vr={class:"button-text"},wr=["id"],Sr={key:1,class:"group"},Lr=m({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(s){const e=s,t=L(!1),n=y(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function o(){t.value=!t.value}return(r,d)=>(a(),l("div",{class:C(["VPNavScreenMenuGroup",{open:t.value}])},[c("button",{class:"button","aria-controls":n.value,"aria-expanded":t.value,onClick:o},[c("span",Vr,V(r.text),1),h(mr,{class:"button-icon"})],8,Pr),c("div",{id:n.value,class:"items"},[(a(!0),l(M,null,B(r.items,p=>(a(),l(M,{key:p.text},["link"in p?(a(),l("div",{key:p.text,class:"item"},[h(ze,{item:p},null,8,["item"])])):(a(),l("div",Sr,[h(yr,{text:p.text,items:p.items},null,8,["text","items"])]))],64))),128))],8,wr)],2))}});const Mr=g(Lr,[["__scopeId","data-v-ba0cbdca"]]),Cr={key:0,class:"VPNavScreenMenu"},Nr=m({__name:"VPNavScreenMenu",setup(s){const{theme:e}=P();return(t,n)=>i(e).nav?(a(),l("nav",Cr,[(a(!0),l(M,null,B(i(e).nav,o=>(a(),l(M,{key:o.text},["link"in o?(a(),$(dr,{key:0,item:o},null,8,["item"])):(a(),$(Mr,{key:1,text:o.text||"",items:o.items},null,8,["text","items"]))],64))),128))])):f("",!0)}}),Ir=m({__name:"VPNavScreenSocialLinks",setup(s){const{theme:e}=P();return(t,n)=>i(e).socialLinks?(a(),$($e,{key:0,class:"VPNavScreenSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}}),Tr={class:"list"},Br=m({__name:"VPNavScreenTranslations",setup(s){const{localeLinks:e,currentLang:t}=X({correspondingLink:!0}),n=L(!1);function o(){n.value=!n.value}return(r,d)=>i(e).length&&i(t).label?(a(),l("div",{key:0,class:C(["VPNavScreenTranslations",{open:n.value}])},[c("button",{class:"title",onClick:o},[h(xe,{class:"icon lang"}),H(" "+V(i(t).label)+" ",1),h(He,{class:"icon chevron"})]),c("ul",Tr,[(a(!0),l(M,null,B(i(e),p=>(a(),l("li",{key:p.link,class:"item"},[h(O,{class:"link",href:p.link},{default:v(()=>[H(V(p.text),1)]),_:2},1032,["href"])]))),128))])],2)):f("",!0)}});const Ar=g(Br,[["__scopeId","data-v-2a5206d0"]]),Hr={class:"container"},xr=m({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(s){const e=L(null),t=Me(q?document.body:null);return(n,o)=>(a(),$(ue,{name:"fade",onEnter:o[0]||(o[0]=r=>t.value=!0),onAfterLeave:o[1]||(o[1]=r=>t.value=!1)},{default:v(()=>[n.open?(a(),l("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[c("div",Hr,[u(n.$slots,"nav-screen-content-before",{},void 0,!0),h(Nr,{class:"menu"}),h(Ar,{class:"translations"}),h(cr,{class:"appearance"}),h(Ir,{class:"social-links"}),u(n.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):f("",!0)]),_:3}))}});const zr=g(xr,[["__scopeId","data-v-a794a04d"]]),Er={key:0,class:"VPNav"},Dr=m({__name:"VPNav",setup(s){const{isScreenOpen:e,closeScreen:t,toggleScreen:n}=Jn(),{frontmatter:o}=P(),r=y(()=>o.value.navbar!==!1);return Ce("close-screen",t),se(()=>{q&&document.documentElement.classList.toggle("hide-nav",!r.value)}),(d,p)=>r.value?(a(),l("header",Er,[h(ar,{"is-screen-open":i(e),onToggleScreen:i(n)},{"nav-bar-title-before":v(()=>[u(d.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[u(d.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[u(d.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[u(d.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),h(zr,{open:i(e)},{"nav-screen-content-before":v(()=>[u(d.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[u(d.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):f("",!0)}});const Fr=g(Dr,[["__scopeId","data-v-f92d2e4c"]]),Or=s=>(z("data-v-c543663c"),s=s(),E(),s),Gr=["role","tabindex"],Ur=Or(()=>c("div",{class:"indicator"},null,-1)),Rr=["onKeydown"],jr={key:1,class:"items"},qr=m({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(s){const e=s,{collapsed:t,collapsible:n,isLink:o,isActiveLink:r,hasActiveLink:d,hasChildren:p,toggle:_}=mt(y(()=>e.item)),k=y(()=>p.value?"section":"div"),N=y(()=>o.value?"a":"div"),T=y(()=>p.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),A=y(()=>o.value?void 0:"button"),I=y(()=>[[`level-${e.depth}`],{collapsible:n.value},{collapsed:t.value},{"is-link":o.value},{"is-active":r.value},{"has-active":d.value}]);function w(b){"key"in b&&b.key!=="Enter"||!e.item.link&&_()}function S(){e.item.link&&_()}return(b,x)=>{const Z=j("VPSidebarItem",!0);return a(),$(G(k.value),{class:C(["VPSidebarItem",I.value])},{default:v(()=>[b.item.text?(a(),l("div",Q({key:0,class:"item",role:A.value},We(b.item.items?{click:w,keydown:w}:{},!0),{tabindex:b.item.items&&0}),[Ur,b.item.link?(a(),$(O,{key:0,tag:N.value,class:"link",href:b.item.link,rel:b.item.rel,target:b.item.target},{default:v(()=>[(a(),$(G(T.value),{class:"text",innerHTML:b.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(a(),$(G(T.value),{key:1,class:"text",innerHTML:b.item.text},null,8,["innerHTML"])),b.item.collapsed!=null?(a(),l("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:S,onKeydown:Ye(S,["enter"]),tabindex:"0"},[h(fe,{class:"caret-icon"})],40,Rr)):f("",!0)],16,Gr)):f("",!0),b.item.items&&b.item.items.length?(a(),l("div",jr,[b.depth<5?(a(!0),l(M,{key:0},B(b.item.items,K=>(a(),$(Z,{key:K.text,item:K,depth:b.depth+1},null,8,["item","depth"]))),128)):f("",!0)])):f("",!0)]),_:1},8,["class"])}}});const Kr=g(qr,[["__scopeId","data-v-c543663c"]]),Ee=s=>(z("data-v-9b5436d7"),s=s(),E(),s),Wr=Ee(()=>c("div",{class:"curtain"},null,-1)),Yr={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},Jr=Ee(()=>c("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),Xr=m({__name:"VPSidebar",props:{open:{type:Boolean}},setup(s){const e=s,{sidebarGroups:t,hasSidebar:n}=D(),o=L(null),r=Me(q?document.body:null);return R([e,o],()=>{var d;e.open?(r.value=!0,(d=o.value)==null||d.focus()):r.value=!1},{immediate:!0,flush:"post"}),(d,p)=>i(n)?(a(),l("aside",{key:0,class:C(["VPSidebar",{open:d.open}]),ref_key:"navEl",ref:o,onClick:p[0]||(p[0]=Je(()=>{},["stop"]))},[Wr,c("nav",Yr,[Jr,u(d.$slots,"sidebar-nav-before",{},void 0,!0),(a(!0),l(M,null,B(i(t),_=>(a(),l("div",{key:_.text,class:"group"},[h(Kr,{item:_,depth:0},null,8,["item"])]))),128)),u(d.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):f("",!0)}});const Zr=g(Xr,[["__scopeId","data-v-9b5436d7"]]),Qr=m({__name:"VPSkipLink",setup(s){const e=ne(),t=L();R(()=>e.path,()=>t.value.focus());function n({target:o}){const r=document.getElementById(decodeURIComponent(o.hash).slice(1));if(r){const d=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",d)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",d),r.focus(),window.scrollTo(0,0)}}return(o,r)=>(a(),l(M,null,[c("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),c("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:n}," Skip to content ")],64))}});const ei=g(Qr,[["__scopeId","data-v-197f0fa6"]]),ti=m({__name:"Layout",setup(s){const{isOpen:e,open:t,close:n}=D(),o=ne();R(()=>o.path,n),ft(e,n);const{frontmatter:r}=P(),d=Xe(),p=y(()=>!!d["home-hero-image"]);return Ce("hero-image-slot-exists",p),(_,k)=>{const N=j("Content");return i(r).layout!==!1?(a(),l("div",{key:0,class:C(["Layout",i(r).pageClass])},[u(_.$slots,"layout-top",{},void 0,!0),h(ei),h(st,{class:"backdrop",show:i(e),onClick:i(n)},null,8,["show","onClick"]),h(Fr,null,{"nav-bar-title-before":v(()=>[u(_.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[u(_.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[u(_.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[u(_.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":v(()=>[u(_.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[u(_.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),h(Yn,{open:i(e),onOpenMenu:i(t)},null,8,["open","onOpenMenu"]),h(Zr,{open:i(e)},{"sidebar-nav-before":v(()=>[u(_.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":v(()=>[u(_.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),h(Ln,null,{"page-top":v(()=>[u(_.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[u(_.$slots,"page-bottom",{},void 0,!0)]),"not-found":v(()=>[u(_.$slots,"not-found",{},void 0,!0)]),"home-hero-before":v(()=>[u(_.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[u(_.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[u(_.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[u(_.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[u(_.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[u(_.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":v(()=>[u(_.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[u(_.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[u(_.$slots,"doc-after",{},void 0,!0)]),"doc-top":v(()=>[u(_.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[u(_.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":v(()=>[u(_.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[u(_.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[u(_.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[u(_.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[u(_.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[u(_.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),h(Tn),u(_.$slots,"layout-bottom",{},void 0,!0)],2)):(a(),$(N,{key:1}))}}});const si=g(ti,[["__scopeId","data-v-bb676018"]]),ni={xmini:[[0,2]],mini:[],small:[[920,6],[768,5],[640,4],[480,3],[0,2]],medium:[[960,5],[832,4],[640,3],[480,2]],big:[[832,3],[640,2]]};function oi({el:s,size:e="medium"}){const t=Ne(n,100);F(()=>{n(),window.addEventListener("resize",t)}),J(()=>{window.removeEventListener("resize",t)});function n(){ai(s.value,e)}}function ai(s,e){const t=s.children.length,n=s.querySelectorAll(".vp-sponsor-grid-item:not(.empty)").length,o=ri(s,e,n);li(s,o,t,n)}function ri(s,e,t){const n=ni[e],o=window.innerWidth;let r=1;return n.some(([d,p])=>{if(o>=d)return r=t0?ui(s,e):di(s,e*-1))}function ui(s,e){for(let t=0;t(a(),l("div",{class:C(["VPSponsorsGrid vp-sponsor-grid",[n.size]]),ref_key:"el",ref:t},[(a(!0),l(M,null,B(n.data,r=>(a(),l("div",{key:r.name,class:"vp-sponsor-grid-item"},[c("a",{class:"vp-sponsor-grid-link",href:r.url,target:"_blank",rel:"sponsored noopener"},[c("article",vi,[c("h4",pi,V(r.name),1),c("img",{class:"vp-sponsor-grid-image",src:r.img,alt:r.name},null,8,hi)])],8,_i)]))),128))],2))}}),mi={key:0,class:"vp-sponsor-tier"},gi=m({__name:"VPSponsors",props:{mode:{default:"normal"},tier:{},size:{},data:{}},setup(s){const e=s,t=y(()=>e.data.some(o=>"items"in o)?e.data:[{tier:e.tier,size:e.size,items:e.data}]);return(n,o)=>(a(),l("div",{class:C(["VPSponsors vp-sponsor",[n.mode]])},[(a(!0),l(M,null,B(t.value,(r,d)=>(a(),l("section",{key:d,class:"vp-sponsor-section"},[r.tier?(a(),l("h3",mi,V(r.tier),1)):f("",!0),h(fi,{size:r.size,data:r.items},null,8,["size","data"])]))),128))],2))}});const bi={class:"VPDocAsideSponsors"},ki=m({__name:"VPDocAsideSponsors",props:{tier:{},size:{},data:{}},setup(s){return(e,t)=>(a(),l("div",bi,[h(gi,{mode:"aside",tier:e.tier,size:e.size,data:e.data},null,8,["tier","size","data"])]))}});const yi={Layout:si,enhanceApp:({app:s})=>{s.component("Badge",Qe)}};export{ki as _,yi as t,P as u}; +import{d as m,o as a,c as l,r as u,n as C,a as H,t as V,_ as g,b as $,w as v,e as f,T as ue,u as De,i as Fe,f as de,g as y,h as L,j as F,k as c,l as i,p as z,m as E,q as U,s as q,v as ie,x as R,y as se,z as J,A as we,B as Oe,C as j,F as M,D as B,E as _e,G as W,H as h,I as G,J as Se,K as ne,L as Q,M as oe,N as Ge,O as Ue,P as Le,Q as Re,R as je,S as qe,U as Ke,V as Me,W as Ce,X as We,Y as Ye,Z as Je,$ as Xe}from"./framework.b7580407.js";const Ze=m({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(s){return(e,t)=>(a(),l("span",{class:C(["VPBadge",e.type])},[u(e.$slots,"default",{},()=>[H(V(e.text),1)],!0)],2))}});const Qe=g(Ze,[["__scopeId","data-v-04be89dc"]]),et={key:0,class:"VPBackdrop"},tt=m({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(s){return(e,t)=>(a(),$(ue,{name:"fade"},{default:v(()=>[e.show?(a(),l("div",et)):f("",!0)]),_:1}))}});const st=g(tt,[["__scopeId","data-v-5bbe8791"]]),P=De;function Ne(s,e){let t,n=!1;return()=>{t&&clearTimeout(t),n?t=setTimeout(s,e):(s(),(n=!0)&&setTimeout(()=>n=!1,e))}}function le(s){return/^\//.test(s)?s:`/${s}`}function Y(s){if(Fe(s))return s;const{site:e}=P(),{pathname:t,search:n,hash:o}=new URL(s,"http://a.com"),r=t.endsWith("/")||t.endsWith(".html")?s:s.replace(/(?:(^\.+)\/)?.*$/,`$1${t.replace(/(\.md)?$/,e.value.cleanUrls?"":".html")}${n}${o}`);return de(r)}function X({removeCurrent:s=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:n,page:o,theme:r}=P(),d=y(()=>{var _,k;return{label:(_=t.value.locales[n.value])==null?void 0:_.label,link:((k=t.value.locales[n.value])==null?void 0:k.link)||(n.value==="root"?"/":`/${n.value}/`)}});return{localeLinks:y(()=>Object.entries(t.value.locales).flatMap(([_,k])=>s&&d.value.label===k.label?[]:{text:k.label,link:nt(k.link||(_==="root"?"/":`/${_}/`),r.value.i18nRouting!==!1&&e,o.value.relativePath.slice(d.value.link.length-1),!t.value.cleanUrls)})),currentLang:d}}function nt(s,e,t,n){return e?s.replace(/\/$/,"")+le(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,n?".html":"")):s}const ot=s=>(z("data-v-8a8c82b4"),s=s(),E(),s),at={class:"NotFound"},rt={class:"code"},it={class:"title"},lt=ot(()=>c("div",{class:"divider"},null,-1)),ct={class:"quote"},ut={class:"action"},dt=["href","aria-label"],_t=m({__name:"NotFound",setup(s){const{site:e,theme:t}=P(),{localeLinks:n}=X({removeCurrent:!1}),o=L("/");return F(()=>{var d;const r=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");n.value.length&&(o.value=((d=n.value.find(({link:p})=>p.startsWith(r)))==null?void 0:d.link)||n.value[0].link)}),(r,d)=>{var p,_,k,N,T;return a(),l("div",at,[c("p",rt,V(((p=i(t).notFound)==null?void 0:p.code)??"404"),1),c("h1",it,V(((_=i(t).notFound)==null?void 0:_.title)??"PAGE NOT FOUND"),1),lt,c("blockquote",ct,V(((k=i(t).notFound)==null?void 0:k.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),c("div",ut,[c("a",{class:"link",href:i(de)(o.value),"aria-label":((N=i(t).notFound)==null?void 0:N.linkLabel)??"go to home"},V(((T=i(t).notFound)==null?void 0:T.linkText)??"Take me home"),9,dt)])])}}});const vt=g(_t,[["__scopeId","data-v-8a8c82b4"]]);function Ie(s,e){if(Array.isArray(s))return ee(s);if(s==null)return[];e=le(e);const t=Object.keys(s).sort((o,r)=>r.split("/").length-o.split("/").length).find(o=>e.startsWith(le(o))),n=t?s[t]:[];return Array.isArray(n)?ee(n):ee(n.items,n.base)}function pt(s){const e=[];let t=0;for(const n in s){const o=s[n];if(o.items){t=e.push(o);continue}e[t]||e.push({items:[]}),e[t].items.push(o)}return e}function ht(s){const e=[];function t(n){for(const o of n)o.text&&o.link&&e.push({text:o.text,link:o.link,docFooterText:o.docFooterText}),o.items&&t(o.items)}return t(s),e}function ce(s,e){return Array.isArray(e)?e.some(t=>ce(s,t)):U(s,e.link)?!0:e.items?ce(s,e.items):!1}function ee(s,e){return[...s].map(t=>{const n={...t},o=n.base||e;return o&&n.link&&(n.link=o+n.link),n.items&&(n.items=ee(n.items,o)),n})}function D(){const{frontmatter:s,page:e,theme:t}=P(),n=ie("(min-width: 960px)"),o=L(!1),r=y(()=>{const S=t.value.sidebar,b=e.value.relativePath;return S?Ie(S,b):[]}),d=L(r.value);R(r,(S,b)=>{JSON.stringify(S)!==JSON.stringify(b)&&(d.value=r.value)});const p=y(()=>s.value.sidebar!==!1&&d.value.length>0&&s.value.layout!=="home"),_=y(()=>k?s.value.aside==null?t.value.aside==="left":s.value.aside==="left":!1),k=y(()=>s.value.layout==="home"?!1:s.value.aside!=null?!!s.value.aside:t.value.aside!==!1),N=y(()=>p.value&&n.value),T=y(()=>p.value?pt(d.value):[]);function A(){o.value=!0}function I(){o.value=!1}function w(){o.value?I():A()}return{isOpen:o,sidebar:d,sidebarGroups:T,hasSidebar:p,hasAside:k,leftAside:_,isSidebarEnabled:N,open:A,close:I,toggle:w}}function ft(s,e){let t;se(()=>{t=s.value?document.activeElement:void 0}),F(()=>{window.addEventListener("keyup",n)}),J(()=>{window.removeEventListener("keyup",n)});function n(o){o.key==="Escape"&&s.value&&(e(),t==null||t.focus())}}const Te=L(q?location.hash:"");q&&window.addEventListener("hashchange",()=>{Te.value=location.hash});function mt(s){const{page:e}=P(),t=L(!1),n=y(()=>s.value.collapsed!=null),o=y(()=>!!s.value.link),r=L(!1),d=()=>{r.value=U(e.value.relativePath,s.value.link)};R([e,s,Te],d),F(d);const p=y(()=>r.value?!0:s.value.items?ce(e.value.relativePath,s.value.items):!1),_=y(()=>!!(s.value.items&&s.value.items.length));se(()=>{t.value=!!(n.value&&s.value.collapsed)}),we(()=>{(r.value||p.value)&&(t.value=!1)});function k(){n.value&&(t.value=!t.value)}return{collapsed:t,collapsible:n,isLink:o,isActiveLink:r,hasActiveLink:p,hasChildren:_,toggle:k}}function gt(){const{hasSidebar:s}=D(),e=ie("(min-width: 960px)"),t=ie("(min-width: 1280px)");return{isAsideEnabled:y(()=>!t.value&&!e.value?!1:s.value?t.value:e.value)}}const bt=71;function ve(s){return typeof s.outline=="object"&&!Array.isArray(s.outline)&&s.outline.label||s.outlineTitle||"On this page"}function pe(s){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const n=Number(t.tagName[1]);return{title:$t(t),link:"#"+t.id,level:n}});return kt(e,s)}function $t(s){let e="";for(const t of s.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function kt(s,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[n,o]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;s=s.filter(d=>d.level>=n&&d.level<=o);const r=[];e:for(let d=0;d=0;_--){const k=s[_];if(k.level{requestAnimationFrame(r),window.addEventListener("scroll",n)}),Oe(()=>{d(location.hash)}),J(()=>{window.removeEventListener("scroll",n)});function r(){if(!t.value)return;const p=[].slice.call(s.value.querySelectorAll(".outline-link")),_=[].slice.call(document.querySelectorAll(".content .header-anchor")).filter(I=>p.some(w=>w.hash===I.hash&&I.offsetParent!==null)),k=window.scrollY,N=window.innerHeight,T=document.body.offsetHeight,A=Math.abs(k+N-T)<1;if(_.length&&A){d(_[_.length-1].hash);return}for(let I=0;I<_.length;I++){const w=_[I],S=_[I+1],[b,x]=Pt(I,w,S);if(b){d(x);return}}}function d(p){o&&o.classList.remove("active"),p==null?o=null:o=s.value.querySelector(`a[href="${decodeURIComponent(p)}"]`);const _=o;_?(_.classList.add("active"),e.value.style.top=_.offsetTop+33+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function Pe(s){return s.parentElement.offsetTop-bt}function Pt(s,e,t){const n=window.scrollY;return s===0&&n===0?[!0,null]:n{const o=j("VPDocOutlineItem",!0);return a(),l("ul",{class:C(t.root?"root":"nested")},[(a(!0),l(M,null,B(t.headers,({children:r,link:d,title:p})=>(a(),l("li",null,[c("a",{class:"outline-link",href:d,onClick:e,title:p},V(p),9,Vt),r!=null&&r.length?(a(),$(o,{key:0,headers:r},null,8,["headers"])):f("",!0)]))),256))],2)}}});const he=g(wt,[["__scopeId","data-v-29e3fa2f"]]),St=s=>(z("data-v-99fa007f"),s=s(),E(),s),Lt={class:"content"},Mt={class:"outline-title",role:"heading","aria-level":"2"},Ct={"aria-labelledby":"doc-outline-aria-label"},Nt=St(()=>c("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),It=m({__name:"VPDocAsideOutline",setup(s){const{frontmatter:e,theme:t}=P(),n=_e([]);W(()=>{n.value=pe(e.value.outline??t.value.outline)});const o=L(),r=L();return yt(o,r),(d,p)=>(a(),l("div",{class:C(["VPDocAsideOutline",{"has-outline":n.value.length>0}]),ref_key:"container",ref:o,role:"navigation"},[c("div",Lt,[c("div",{class:"outline-marker",ref_key:"marker",ref:r},null,512),c("div",Mt,V(i(ve)(i(t))),1),c("nav",Ct,[Nt,h(he,{headers:n.value,root:!0},null,8,["headers"])])])],2))}});const Tt=g(It,[["__scopeId","data-v-99fa007f"]]),Bt={class:"VPDocAsideCarbonAds"},At=m({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(s){const e=()=>null;return(t,n)=>(a(),l("div",Bt,[h(i(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),Ht=s=>(z("data-v-f5b3965e"),s=s(),E(),s),xt={class:"VPDocAside"},zt=Ht(()=>c("div",{class:"spacer"},null,-1)),Et=m({__name:"VPDocAside",setup(s){const{theme:e}=P();return(t,n)=>(a(),l("div",xt,[u(t.$slots,"aside-top",{},void 0,!0),u(t.$slots,"aside-outline-before",{},void 0,!0),h(Tt),u(t.$slots,"aside-outline-after",{},void 0,!0),zt,u(t.$slots,"aside-ads-before",{},void 0,!0),i(e).carbonAds?(a(),$(At,{key:0,"carbon-ads":i(e).carbonAds},null,8,["carbon-ads"])):f("",!0),u(t.$slots,"aside-ads-after",{},void 0,!0),u(t.$slots,"aside-bottom",{},void 0,!0)]))}});const Dt=g(Et,[["__scopeId","data-v-f5b3965e"]]);function Ft(){const{theme:s,page:e}=P();return y(()=>{const{text:t="Edit this page",pattern:n=""}=s.value.editLink||{};let o;return typeof n=="function"?o=n(e.value):o=n.replace(/:path/g,e.value.filePath),{url:o,text:t}})}function Ot(){const{page:s,theme:e,frontmatter:t}=P();return y(()=>{var _,k,N,T,A,I,w,S;const n=Ie(e.value.sidebar,s.value.relativePath),o=ht(n),r=o.findIndex(b=>U(s.value.relativePath,b.link)),d=((_=e.value.docFooter)==null?void 0:_.prev)===!1&&!t.value.prev||t.value.prev===!1,p=((k=e.value.docFooter)==null?void 0:k.next)===!1&&!t.value.next||t.value.next===!1;return{prev:d?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((N=o[r-1])==null?void 0:N.docFooterText)??((T=o[r-1])==null?void 0:T.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((A=o[r-1])==null?void 0:A.link)},next:p?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((I=o[r+1])==null?void 0:I.docFooterText)??((w=o[r+1])==null?void 0:w.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((S=o[r+1])==null?void 0:S.link)}}})}const Gt={},Ut={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Rt=c("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),jt=c("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),qt=[Rt,jt];function Kt(s,e){return a(),l("svg",Ut,qt)}const Wt=g(Gt,[["render",Kt]]),O=m({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(s){const e=s,t=y(()=>e.tag??(e.href?"a":"span")),n=y(()=>e.href&&Se.test(e.href));return(o,r)=>(a(),$(G(t.value),{class:C(["VPLink",{link:o.href,"vp-external-link-icon":n.value,"no-icon":o.noIcon}]),href:o.href?i(Y)(o.href):void 0,target:o.target??(n.value?"_blank":void 0),rel:o.rel??(n.value?"noreferrer":void 0)},{default:v(()=>[u(o.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),Yt={class:"VPLastUpdated"},Jt=["datetime"],Xt=m({__name:"VPDocFooterLastUpdated",setup(s){const{theme:e,page:t,frontmatter:n,lang:o}=P(),r=y(()=>new Date(n.value.lastUpdated??t.value.lastUpdated)),d=y(()=>r.value.toISOString()),p=L("");return F(()=>{se(()=>{var _,k,N;p.value=new Intl.DateTimeFormat((k=(_=e.value.lastUpdated)==null?void 0:_.formatOptions)!=null&&k.forceLocale?o.value:void 0,((N=e.value.lastUpdated)==null?void 0:N.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(r.value)})}),(_,k)=>{var N;return a(),l("p",Yt,[H(V(((N=i(e).lastUpdated)==null?void 0:N.text)||i(e).lastUpdatedText||"Last updated")+": ",1),c("time",{datetime:d.value},V(p.value),9,Jt)])}}});const Zt=g(Xt,[["__scopeId","data-v-ec8405ef"]]),Qt={key:0,class:"VPDocFooter"},es={key:0,class:"edit-info"},ts={key:0,class:"edit-link"},ss={key:1,class:"last-updated"},ns={key:1,class:"prev-next"},os={class:"pager"},as=["href"],rs=["innerHTML"],is=["innerHTML"],ls={class:"pager"},cs=["href"],us=["innerHTML"],ds=["innerHTML"],_s=m({__name:"VPDocFooter",setup(s){const{theme:e,page:t,frontmatter:n}=P(),o=Ft(),r=Ot(),d=y(()=>e.value.editLink&&n.value.editLink!==!1),p=y(()=>t.value.lastUpdated&&n.value.lastUpdated!==!1),_=y(()=>d.value||p.value||r.value.prev||r.value.next);return(k,N)=>{var T,A,I,w,S,b;return _.value?(a(),l("footer",Qt,[u(k.$slots,"doc-footer-before",{},void 0,!0),d.value||p.value?(a(),l("div",es,[d.value?(a(),l("div",ts,[h(O,{class:"edit-link-button",href:i(o).url,"no-icon":!0},{default:v(()=>[h(Wt,{class:"edit-link-icon","aria-label":"edit icon"}),H(" "+V(i(o).text),1)]),_:1},8,["href"])])):f("",!0),p.value?(a(),l("div",ss,[h(Zt)])):f("",!0)])):f("",!0),(T=i(r).prev)!=null&&T.link||(A=i(r).next)!=null&&A.link?(a(),l("nav",ns,[c("div",os,[(I=i(r).prev)!=null&&I.link?(a(),l("a",{key:0,class:"pager-link prev",href:i(Y)(i(r).prev.link)},[c("span",{class:"desc",innerHTML:((w=i(e).docFooter)==null?void 0:w.prev)||"Previous page"},null,8,rs),c("span",{class:"title",innerHTML:i(r).prev.text},null,8,is)],8,as)):f("",!0)]),c("div",ls,[(S=i(r).next)!=null&&S.link?(a(),l("a",{key:0,class:"pager-link next",href:i(Y)(i(r).next.link)},[c("span",{class:"desc",innerHTML:((b=i(e).docFooter)==null?void 0:b.next)||"Next page"},null,8,us),c("span",{class:"title",innerHTML:i(r).next.text},null,8,ds)],8,cs)):f("",!0)])])):f("",!0)])):f("",!0)}}});const vs=g(_s,[["__scopeId","data-v-bae355c8"]]),ps={},hs={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},fs=c("path",{d:"M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"},null,-1),ms=[fs];function gs(s,e){return a(),l("svg",hs,ms)}const fe=g(ps,[["render",gs]]),bs={key:0,class:"VPDocOutlineDropdown"},$s={key:0,class:"items"},ks=m({__name:"VPDocOutlineDropdown",setup(s){const{frontmatter:e,theme:t}=P(),n=L(!1);W(()=>{n.value=!1});const o=_e([]);return W(()=>{o.value=pe(e.value.outline??t.value.outline)}),(r,d)=>o.value.length>0?(a(),l("div",bs,[c("button",{onClick:d[0]||(d[0]=p=>n.value=!n.value),class:C({open:n.value})},[H(V(i(ve)(i(t)))+" ",1),h(fe,{class:"icon"})],2),n.value?(a(),l("div",$s,[h(he,{headers:o.value},null,8,["headers"])])):f("",!0)])):f("",!0)}});const ys=g(ks,[["__scopeId","data-v-23cf0713"]]),Ps=s=>(z("data-v-39e6c32d"),s=s(),E(),s),Vs={class:"container"},ws=Ps(()=>c("div",{class:"aside-curtain"},null,-1)),Ss={class:"aside-container"},Ls={class:"aside-content"},Ms={class:"content"},Cs={class:"content-container"},Ns={class:"main"},Is=m({__name:"VPDoc",setup(s){const{theme:e}=P(),t=ne(),{hasSidebar:n,hasAside:o,leftAside:r}=D(),d=y(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(p,_)=>{const k=j("Content");return a(),l("div",{class:C(["VPDoc",{"has-sidebar":i(n),"has-aside":i(o)}])},[u(p.$slots,"doc-top",{},void 0,!0),c("div",Vs,[i(o)?(a(),l("div",{key:0,class:C(["aside",{"left-aside":i(r)}])},[ws,c("div",Ss,[c("div",Ls,[h(Dt,null,{"aside-top":v(()=>[u(p.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[u(p.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[u(p.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[u(p.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[u(p.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[u(p.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):f("",!0),c("div",Ms,[c("div",Cs,[u(p.$slots,"doc-before",{},void 0,!0),h(ys),c("main",Ns,[h(k,{class:C(["vp-doc",[d.value,i(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),h(vs,null,{"doc-footer-before":v(()=>[u(p.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),u(p.$slots,"doc-after",{},void 0,!0)])])]),u(p.$slots,"doc-bottom",{},void 0,!0)],2)}}});const Ts=g(Is,[["__scopeId","data-v-39e6c32d"]]),Bs=m({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{}},setup(s){const e=s,t=y(()=>e.href&&Se.test(e.href)),n=y(()=>e.tag||e.href?"a":"button");return(o,r)=>(a(),$(G(n.value),{class:C(["VPButton",[o.size,o.theme]]),href:o.href?i(Y)(o.href):void 0,target:t.value?"_blank":void 0,rel:t.value?"noreferrer":void 0},{default:v(()=>[H(V(o.text),1)]),_:1},8,["class","href","target","rel"]))}});const As=g(Bs,[["__scopeId","data-v-c5bc28bc"]]),Hs=["src","alt"],xs=m({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(s){return(e,t)=>{const n=j("VPImage",!0);return e.image?(a(),l(M,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),l("img",Q({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:i(de)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,Hs)):(a(),l(M,{key:1},[h(n,Q({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),h(n,Q({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):f("",!0)}}});const te=g(xs,[["__scopeId","data-v-6ebf9bdf"]]),zs=s=>(z("data-v-95ba8d2c"),s=s(),E(),s),Es={class:"container"},Ds={class:"main"},Fs={key:0,class:"name"},Os=["innerHTML"],Gs=["innerHTML"],Us=["innerHTML"],Rs={key:0,class:"actions"},js={key:0,class:"image"},qs={class:"image-container"},Ks=zs(()=>c("div",{class:"image-bg"},null,-1)),Ws=m({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(s){const e=oe("hero-image-slot-exists");return(t,n)=>(a(),l("div",{class:C(["VPHero",{"has-image":t.image||i(e)}])},[c("div",Es,[c("div",Ds,[u(t.$slots,"home-hero-info",{},()=>[t.name?(a(),l("h1",Fs,[c("span",{innerHTML:t.name,class:"clip"},null,8,Os)])):f("",!0),t.text?(a(),l("p",{key:1,innerHTML:t.text,class:"text"},null,8,Gs)):f("",!0),t.tagline?(a(),l("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,Us)):f("",!0)],!0),t.actions?(a(),l("div",Rs,[(a(!0),l(M,null,B(t.actions,o=>(a(),l("div",{key:o.link,class:"action"},[h(As,{tag:"a",size:"medium",theme:o.theme,text:o.text,href:o.link},null,8,["theme","text","href"])]))),128))])):f("",!0)]),t.image||i(e)?(a(),l("div",js,[c("div",qs,[Ks,u(t.$slots,"home-hero-image",{},()=>[t.image?(a(),$(te,{key:0,class:"image-src",image:t.image},null,8,["image"])):f("",!0)],!0)])])):f("",!0)])],2))}});const Ys=g(Ws,[["__scopeId","data-v-95ba8d2c"]]),Js=m({__name:"VPHomeHero",setup(s){const{frontmatter:e}=P();return(t,n)=>i(e).hero?(a(),$(Ys,{key:0,class:"VPHomeHero",name:i(e).hero.name,text:i(e).hero.text,tagline:i(e).hero.tagline,image:i(e).hero.image,actions:i(e).hero.actions},{"home-hero-info":v(()=>[u(t.$slots,"home-hero-info")]),"home-hero-image":v(()=>[u(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):f("",!0)}}),Xs={},Zs={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Qs=c("path",{d:"M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"},null,-1),en=[Qs];function tn(s,e){return a(),l("svg",Zs,en)}const sn=g(Xs,[["render",tn]]),nn={class:"box"},on={key:0,class:"icon"},an=["innerHTML"],rn=["innerHTML"],ln=["innerHTML"],cn={key:4,class:"link-text"},un={class:"link-text-value"},dn=m({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(s){return(e,t)=>(a(),$(O,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:v(()=>[c("article",nn,[typeof e.icon=="object"&&e.icon.wrap?(a(),l("div",on,[h(te,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(a(),$(te,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(a(),l("div",{key:2,class:"icon",innerHTML:e.icon},null,8,an)):f("",!0),c("h2",{class:"title",innerHTML:e.title},null,8,rn),e.details?(a(),l("p",{key:3,class:"details",innerHTML:e.details},null,8,ln)):f("",!0),e.linkText?(a(),l("div",cn,[c("p",un,[H(V(e.linkText)+" ",1),h(sn,{class:"link-text-icon"})])])):f("",!0)])]),_:1},8,["href","rel","target","tag"]))}});const _n=g(dn,[["__scopeId","data-v-5826beaa"]]),vn={key:0,class:"VPFeatures"},pn={class:"container"},hn={class:"items"},fn=m({__name:"VPFeatures",props:{features:{}},setup(s){const e=s,t=y(()=>{const n=e.features.length;if(n){if(n===2)return"grid-2";if(n===3)return"grid-3";if(n%3===0)return"grid-6";if(n>3)return"grid-4"}else return});return(n,o)=>n.features?(a(),l("div",vn,[c("div",pn,[c("div",hn,[(a(!0),l(M,null,B(n.features,r=>(a(),l("div",{key:r.title,class:C(["item",[t.value]])},[h(_n,{icon:r.icon,title:r.title,details:r.details,link:r.link,"link-text":r.linkText,rel:r.rel,target:r.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):f("",!0)}});const mn=g(fn,[["__scopeId","data-v-8aecaca0"]]),gn=m({__name:"VPHomeFeatures",setup(s){const{frontmatter:e}=P();return(t,n)=>i(e).features?(a(),$(mn,{key:0,class:"VPHomeFeatures",features:i(e).features},null,8,["features"])):f("",!0)}}),bn={class:"VPHome"},$n=m({__name:"VPHome",setup(s){return(e,t)=>{const n=j("Content");return a(),l("div",bn,[u(e.$slots,"home-hero-before",{},void 0,!0),h(Js,null,{"home-hero-info":v(()=>[u(e.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[u(e.$slots,"home-hero-image",{},void 0,!0)]),_:3}),u(e.$slots,"home-hero-after",{},void 0,!0),u(e.$slots,"home-features-before",{},void 0,!0),h(gn),u(e.$slots,"home-features-after",{},void 0,!0),h(n)])}}});const kn=g($n,[["__scopeId","data-v-458cb9ca"]]),yn={},Pn={class:"VPPage"};function Vn(s,e){const t=j("Content");return a(),l("div",Pn,[u(s.$slots,"page-top"),h(t),u(s.$slots,"page-bottom")])}const wn=g(yn,[["render",Vn]]),Sn=m({__name:"VPContent",setup(s){const{page:e,frontmatter:t}=P(),{hasSidebar:n}=D();return(o,r)=>(a(),l("div",{class:C(["VPContent",{"has-sidebar":i(n),"is-home":i(t).layout==="home"}]),id:"VPContent"},[i(e).isNotFound?u(o.$slots,"not-found",{key:0},()=>[h(vt)],!0):i(t).layout==="page"?(a(),$(wn,{key:1},{"page-top":v(()=>[u(o.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[u(o.$slots,"page-bottom",{},void 0,!0)]),_:3})):i(t).layout==="home"?(a(),$(kn,{key:2},{"home-hero-before":v(()=>[u(o.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[u(o.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[u(o.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[u(o.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[u(o.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[u(o.$slots,"home-features-after",{},void 0,!0)]),_:3})):i(t).layout&&i(t).layout!=="doc"?(a(),$(G(i(t).layout),{key:3})):(a(),$(Ts,{key:4},{"doc-top":v(()=>[u(o.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[u(o.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":v(()=>[u(o.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[u(o.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[u(o.$slots,"doc-after",{},void 0,!0)]),"aside-top":v(()=>[u(o.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":v(()=>[u(o.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[u(o.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[u(o.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[u(o.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":v(()=>[u(o.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}});const Ln=g(Sn,[["__scopeId","data-v-f3ed2c70"]]),Mn={class:"container"},Cn=["innerHTML"],Nn=["innerHTML"],In=m({__name:"VPFooter",setup(s){const{theme:e,frontmatter:t}=P(),{hasSidebar:n}=D();return(o,r)=>i(e).footer&&i(t).footer!==!1?(a(),l("footer",{key:0,class:C(["VPFooter",{"has-sidebar":i(n)}])},[c("div",Mn,[i(e).footer.message?(a(),l("p",{key:0,class:"message",innerHTML:i(e).footer.message},null,8,Cn)):f("",!0),i(e).footer.copyright?(a(),l("p",{key:1,class:"copyright",innerHTML:i(e).footer.copyright},null,8,Nn)):f("",!0)])],2)):f("",!0)}});const Tn=g(In,[["__scopeId","data-v-b69a1592"]]),Bn={class:"header"},An={class:"outline"},Hn=m({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(s){const e=s,{theme:t}=P(),n=L(!1),o=L(0),r=L();W(()=>{n.value=!1});function d(){n.value=!n.value,o.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function p(k){k.target.classList.contains("outline-link")&&(r.value&&(r.value.style.transition="none"),Ue(()=>{n.value=!1}))}function _(){n.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(k,N)=>(a(),l("div",{class:"VPLocalNavOutlineDropdown",style:Ge({"--vp-vh":o.value+"px"})},[k.headers.length>0?(a(),l("button",{key:0,onClick:d,class:C({open:n.value})},[H(V(i(ve)(i(t)))+" ",1),h(fe,{class:"icon"})],2)):(a(),l("button",{key:1,onClick:_},V(i(t).returnToTopLabel||"Return to top"),1)),h(ue,{name:"flyout"},{default:v(()=>[n.value?(a(),l("div",{key:0,ref_key:"items",ref:r,class:"items",onClick:p},[c("div",Bn,[c("a",{class:"top-link",href:"#",onClick:_},V(i(t).returnToTopLabel||"Return to top"),1)]),c("div",An,[h(he,{headers:k.headers},null,8,["headers"])])],512)):f("",!0)]),_:1})],4))}});const xn=g(Hn,[["__scopeId","data-v-44ae7a43"]]),zn={},En={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Dn=c("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),Fn=c("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),On=c("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),Gn=c("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),Un=[Dn,Fn,On,Gn];function Rn(s,e){return a(),l("svg",En,Un)}const jn=g(zn,[["render",Rn]]),qn=["aria-expanded"],Kn={class:"menu-text"},Wn=m({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(s){const{theme:e,frontmatter:t}=P(),{hasSidebar:n}=D(),{y:o}=Le(),r=_e([]),d=L(0);F(()=>{d.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),W(()=>{r.value=pe(t.value.outline??e.value.outline)});const p=y(()=>r.value.length===0&&!n.value),_=y(()=>({VPLocalNav:!0,fixed:p.value,"reached-top":o.value>=d.value}));return(k,N)=>i(t).layout!=="home"&&(!p.value||i(o)>=d.value)?(a(),l("div",{key:0,class:C(_.value)},[i(n)?(a(),l("button",{key:0,class:"menu","aria-expanded":k.open,"aria-controls":"VPSidebarNav",onClick:N[0]||(N[0]=T=>k.$emit("open-menu"))},[h(jn,{class:"menu-icon"}),c("span",Kn,V(i(e).sidebarMenuLabel||"Menu"),1)],8,qn)):f("",!0),h(xn,{headers:r.value,navHeight:d.value},null,8,["headers","navHeight"])],2)):f("",!0)}});const Yn=g(Wn,[["__scopeId","data-v-a41c4a1c"]]);function Jn(){const s=L(!1);function e(){s.value=!0,window.addEventListener("resize",o)}function t(){s.value=!1,window.removeEventListener("resize",o)}function n(){s.value?t():e()}function o(){window.outerWidth>=768&&t()}const r=ne();return R(()=>r.path,t),{isScreenOpen:s,openScreen:e,closeScreen:t,toggleScreen:n}}const Xn={},Zn={class:"VPSwitch",type:"button",role:"switch"},Qn={class:"check"},eo={key:0,class:"icon"};function to(s,e){return a(),l("button",Zn,[c("span",Qn,[s.$slots.default?(a(),l("span",eo,[u(s.$slots,"default",{},void 0,!0)])):f("",!0)])])}const so=g(Xn,[["render",to],["__scopeId","data-v-56eb52d1"]]),no={},oo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ao=c("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),ro=[ao];function io(s,e){return a(),l("svg",oo,ro)}const lo=g(no,[["render",io]]),co={},uo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},_o=Re('',9),vo=[_o];function po(s,e){return a(),l("svg",uo,vo)}const ho=g(co,[["render",po]]),fo=m({__name:"VPSwitchAppearance",setup(s){const{isDark:e}=P(),t=oe("toggle-appearance",()=>{e.value=!e.value});return(n,o)=>(a(),$(so,{title:"toggle dark mode",class:"VPSwitchAppearance","aria-checked":i(e),onClick:i(t)},{default:v(()=>[h(ho,{class:"sun"}),h(lo,{class:"moon"})]),_:1},8,["aria-checked","onClick"]))}});const me=g(fo,[["__scopeId","data-v-65b67168"]]),mo={key:0,class:"VPNavBarAppearance"},go=m({__name:"VPNavBarAppearance",setup(s){const{site:e}=P();return(t,n)=>i(e).appearance&&i(e).appearance!=="force-dark"?(a(),l("div",mo,[h(me)])):f("",!0)}});const bo=g(go,[["__scopeId","data-v-dc7cad42"]]),ge=L();let Be=!1,re=0;function $o(s){const e=L(!1);if(q){!Be&&ko(),re++;const t=R(ge,n=>{var o,r,d;n===s.el.value||(o=s.el.value)!=null&&o.contains(n)?(e.value=!0,(r=s.onFocus)==null||r.call(s)):(e.value=!1,(d=s.onBlur)==null||d.call(s))});J(()=>{t(),re--,re||yo()})}return je(e)}function ko(){document.addEventListener("focusin",Ae),Be=!0,ge.value=document.activeElement}function yo(){document.removeEventListener("focusin",Ae)}function Ae(){ge.value=document.activeElement}const Po={},Vo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},wo=c("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),So=[wo];function Lo(s,e){return a(),l("svg",Vo,So)}const He=g(Po,[["render",Lo]]),Mo={},Co={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},No=c("circle",{cx:"12",cy:"12",r:"2"},null,-1),Io=c("circle",{cx:"19",cy:"12",r:"2"},null,-1),To=c("circle",{cx:"5",cy:"12",r:"2"},null,-1),Bo=[No,Io,To];function Ao(s,e){return a(),l("svg",Co,Bo)}const Ho=g(Mo,[["render",Ao]]),xo={class:"VPMenuLink"},zo=m({__name:"VPMenuLink",props:{item:{}},setup(s){const{page:e}=P();return(t,n)=>(a(),l("div",xo,[h(O,{class:C({active:i(U)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:v(()=>[H(V(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}});const ae=g(zo,[["__scopeId","data-v-ec5470f2"]]),Eo={class:"VPMenuGroup"},Do={key:0,class:"title"},Fo=m({__name:"VPMenuGroup",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),l("div",Eo,[e.text?(a(),l("p",Do,V(e.text),1)):f("",!0),(a(!0),l(M,null,B(e.items,n=>(a(),l(M,null,["link"in n?(a(),$(ae,{key:0,item:n},null,8,["item"])):f("",!0)],64))),256))]))}});const Oo=g(Fo,[["__scopeId","data-v-b9d0e57b"]]),Go={class:"VPMenu"},Uo={key:0,class:"items"},Ro=m({__name:"VPMenu",props:{items:{}},setup(s){return(e,t)=>(a(),l("div",Go,[e.items?(a(),l("div",Uo,[(a(!0),l(M,null,B(e.items,n=>(a(),l(M,{key:n.text},["link"in n?(a(),$(ae,{key:0,item:n},null,8,["item"])):(a(),$(Oo,{key:1,text:n.text,items:n.items},null,8,["text","items"]))],64))),128))])):f("",!0),u(e.$slots,"default",{},void 0,!0)]))}});const jo=g(Ro,[["__scopeId","data-v-17c3596a"]]),qo=["aria-expanded","aria-label"],Ko={key:0,class:"text"},Wo=["innerHTML"],Yo={class:"menu"},Jo=m({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(s){const e=L(!1),t=L();$o({el:t,onBlur:n});function n(){e.value=!1}return(o,r)=>(a(),l("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:r[1]||(r[1]=d=>e.value=!0),onMouseleave:r[2]||(r[2]=d=>e.value=!1)},[c("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":o.label,onClick:r[0]||(r[0]=d=>e.value=!e.value)},[o.button||o.icon?(a(),l("span",Ko,[o.icon?(a(),$(G(o.icon),{key:0,class:"option-icon"})):f("",!0),o.button?(a(),l("span",{key:1,innerHTML:o.button},null,8,Wo)):f("",!0),h(He,{class:"text-icon"})])):(a(),$(Ho,{key:1,class:"icon"}))],8,qo),c("div",Yo,[h(jo,{items:o.items},{default:v(()=>[u(o.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}});const be=g(Jo,[["__scopeId","data-v-62bba1f9"]]),Xo={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',mastodon:'Mastodon',slack:'Slack',twitter:'Twitter',x:'X',youtube:'YouTube'},Zo=["href","aria-label","innerHTML"],Qo=m({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(s){const e=s,t=y(()=>typeof e.icon=="object"?e.icon.svg:Xo[e.icon]);return(n,o)=>(a(),l("a",{class:"VPSocialLink no-icon",href:n.link,"aria-label":n.ariaLabel??(typeof n.icon=="string"?n.icon:""),target:"_blank",rel:"noopener",innerHTML:t.value},null,8,Zo))}});const ea=g(Qo,[["__scopeId","data-v-1b61e2c7"]]),ta={class:"VPSocialLinks"},sa=m({__name:"VPSocialLinks",props:{links:{}},setup(s){return(e,t)=>(a(),l("div",ta,[(a(!0),l(M,null,B(e.links,({link:n,icon:o,ariaLabel:r})=>(a(),$(ea,{key:n,icon:o,link:n,ariaLabel:r},null,8,["icon","link","ariaLabel"]))),128))]))}});const $e=g(sa,[["__scopeId","data-v-8a65be56"]]),na={key:0,class:"group translations"},oa={class:"trans-title"},aa={key:1,class:"group"},ra={class:"item appearance"},ia={class:"label"},la={class:"appearance-action"},ca={key:2,class:"group"},ua={class:"item social-links"},da=m({__name:"VPNavBarExtra",setup(s){const{site:e,theme:t}=P(),{localeLinks:n,currentLang:o}=X({correspondingLink:!0}),r=y(()=>n.value.length&&o.value.label||e.value.appearance||t.value.socialLinks);return(d,p)=>r.value?(a(),$(be,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:v(()=>[i(n).length&&i(o).label?(a(),l("div",na,[c("p",oa,V(i(o).label),1),(a(!0),l(M,null,B(i(n),_=>(a(),$(ae,{key:_.link,item:_},null,8,["item"]))),128))])):f("",!0),i(e).appearance?(a(),l("div",aa,[c("div",ra,[c("p",ia,V(i(t).darkModeSwitchLabel||"Appearance"),1),c("div",la,[h(me)])])])):f("",!0),i(t).socialLinks?(a(),l("div",ca,[c("div",ua,[h($e,{class:"social-links-list",links:i(t).socialLinks},null,8,["links"])])])):f("",!0)]),_:1})):f("",!0)}});const _a=g(da,[["__scopeId","data-v-e5c8c6ca"]]),va=s=>(z("data-v-f865e4ad"),s=s(),E(),s),pa=["aria-expanded"],ha=va(()=>c("span",{class:"container"},[c("span",{class:"top"}),c("span",{class:"middle"}),c("span",{class:"bottom"})],-1)),fa=[ha],ma=m({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(s){return(e,t)=>(a(),l("button",{type:"button",class:C(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=n=>e.$emit("click"))},fa,10,pa))}});const ga=g(ma,[["__scopeId","data-v-f865e4ad"]]),ba=["innerHTML"],$a=m({__name:"VPNavBarMenuLink",props:{item:{}},setup(s){const{page:e}=P();return(t,n)=>(a(),$(O,{class:C({VPNavBarMenuLink:!0,active:i(U)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:v(()=>[c("span",{innerHTML:t.item.text},null,8,ba)]),_:1},8,["class","href","target","rel"]))}});const ka=g($a,[["__scopeId","data-v-416f44b0"]]),ya=m({__name:"VPNavBarMenuGroup",props:{item:{}},setup(s){const e=s,{page:t}=P(),n=r=>"link"in r?U(t.value.relativePath,r.link,!!e.item.activeMatch):r.items.some(n),o=y(()=>n(e.item));return(r,d)=>(a(),$(be,{class:C({VPNavBarMenuGroup:!0,active:i(U)(i(t).relativePath,r.item.activeMatch,!!r.item.activeMatch)||o.value}),button:r.item.text,items:r.item.items},null,8,["class","button","items"]))}}),Pa=s=>(z("data-v-183ec936"),s=s(),E(),s),Va={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},wa=Pa(()=>c("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Sa=m({__name:"VPNavBarMenu",setup(s){const{theme:e}=P();return(t,n)=>i(e).nav?(a(),l("nav",Va,[wa,(a(!0),l(M,null,B(i(e).nav,o=>(a(),l(M,{key:o.text},["link"in o?(a(),$(ka,{key:0,item:o},null,8,["item"])):(a(),$(ya,{key:1,item:o},null,8,["item"]))],64))),128))])):f("",!0)}});const La=g(Sa,[["__scopeId","data-v-183ec936"]]);const Ma={type:"button",class:"DocSearch DocSearch-Button","aria-label":"Search"},Ca={class:"DocSearch-Button-Container"},Na=c("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20","aria-label":"search icon"},[c("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Ia={class:"DocSearch-Button-Placeholder"},Ta=c("span",{class:"DocSearch-Button-Keys"},[c("kbd",{class:"DocSearch-Button-Key"}),c("kbd",{class:"DocSearch-Button-Key"},"K")],-1),Ve=m({__name:"VPNavBarSearchButton",props:{placeholder:{}},setup(s){return(e,t)=>(a(),l("button",Ma,[c("span",Ca,[Na,c("span",Ia,V(e.placeholder),1)]),Ta]))}});const Ba={class:"VPNavBarSearch"},Aa={id:"local-search"},Ha={key:1,id:"docsearch"},xa=m({__name:"VPNavBarSearch",setup(s){const e=()=>null,t=qe(()=>Ke(()=>import("./VPAlgoliaSearchBox.c32b1d6a.js"),["assets/chunks/VPAlgoliaSearchBox.c32b1d6a.js","assets/chunks/framework.b7580407.js"])),{theme:n,localeIndex:o}=P(),r=L(!1),d=L(!1),p=y(()=>{var S,b,x,Z,K,ke,ye;const w=((S=n.value.search)==null?void 0:S.options)??n.value.algolia;return((K=(Z=(x=(b=w==null?void 0:w.locales)==null?void 0:b[o.value])==null?void 0:x.translations)==null?void 0:Z.button)==null?void 0:K.buttonText)||((ye=(ke=w==null?void 0:w.translations)==null?void 0:ke.button)==null?void 0:ye.buttonText)||"Search"}),_=()=>{const w="VPAlgoliaPreconnect";(window.requestIdleCallback||setTimeout)(()=>{var x;const b=document.createElement("link");b.id=w,b.rel="preconnect",b.href=`https://${(((x=n.value.search)==null?void 0:x.options)??n.value.algolia).appId}-dsn.algolia.net`,b.crossOrigin="",document.head.appendChild(b)})};F(()=>{_();const w=b=>{(b.key.toLowerCase()==="k"&&(b.metaKey||b.ctrlKey)||!T(b)&&b.key==="/")&&(b.preventDefault(),k(),S())},S=()=>{window.removeEventListener("keydown",w)};window.addEventListener("keydown",w),J(S)});function k(){r.value||(r.value=!0,setTimeout(N,16))}function N(){const w=new Event("keydown");w.key="k",w.metaKey=!0,window.dispatchEvent(w),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||N()},16)}function T(w){const S=w.target,b=S.tagName;return S.isContentEditable||b==="INPUT"||b==="SELECT"||b==="TEXTAREA"}const A=L(!1),I="algolia";return(w,S)=>{var b;return a(),l("div",Ba,[i(I)==="local"?(a(),l(M,{key:0},[A.value?(a(),$(i(e),{key:0,placeholder:p.value,onClose:S[0]||(S[0]=x=>A.value=!1)},null,8,["placeholder"])):f("",!0),c("div",Aa,[h(Ve,{placeholder:p.value,onClick:S[1]||(S[1]=x=>A.value=!0)},null,8,["placeholder"])])],64)):i(I)==="algolia"?(a(),l(M,{key:1},[r.value?(a(),$(i(t),{key:0,algolia:((b=i(n).search)==null?void 0:b.options)??i(n).algolia,onVnodeBeforeMount:S[2]||(S[2]=x=>d.value=!0)},null,8,["algolia"])):f("",!0),d.value?f("",!0):(a(),l("div",Ha,[h(Ve,{placeholder:p.value,onClick:k},null,8,["placeholder"])]))],64)):f("",!0)])}}});const za=m({__name:"VPNavBarSocialLinks",setup(s){const{theme:e}=P();return(t,n)=>i(e).socialLinks?(a(),$($e,{key:0,class:"VPNavBarSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}});const Ea=g(za,[["__scopeId","data-v-aaebde08"]]),Da=["href"],Fa=m({__name:"VPNavBarTitle",setup(s){const{site:e,theme:t}=P(),{hasSidebar:n}=D(),{currentLang:o}=X();return(r,d)=>(a(),l("div",{class:C(["VPNavBarTitle",{"has-sidebar":i(n)}])},[c("a",{class:"title",href:i(t).logoLink??i(Y)(i(o).link)},[u(r.$slots,"nav-bar-title-before",{},void 0,!0),i(t).logo?(a(),$(te,{key:0,class:"logo",image:i(t).logo},null,8,["image"])):f("",!0),i(t).siteTitle?(a(),l(M,{key:1},[H(V(i(t).siteTitle),1)],64)):i(t).siteTitle===void 0?(a(),l(M,{key:2},[H(V(i(e).title),1)],64)):f("",!0),u(r.$slots,"nav-bar-title-after",{},void 0,!0)],8,Da)],2))}});const Oa=g(Fa,[["__scopeId","data-v-87c32abd"]]),Ga={},Ua={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Ra=c("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),ja=c("path",{d:" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z ",class:"css-c4d79v"},null,-1),qa=[Ra,ja];function Ka(s,e){return a(),l("svg",Ua,qa)}const xe=g(Ga,[["render",Ka]]),Wa={class:"items"},Ya={class:"title"},Ja=m({__name:"VPNavBarTranslations",setup(s){const{theme:e}=P(),{localeLinks:t,currentLang:n}=X({correspondingLink:!0});return(o,r)=>i(t).length&&i(n).label?(a(),$(be,{key:0,class:"VPNavBarTranslations",icon:xe,label:i(e).langMenuLabel||"Change language"},{default:v(()=>[c("div",Wa,[c("p",Ya,V(i(n).label),1),(a(!0),l(M,null,B(i(t),d=>(a(),$(ae,{key:d.link,item:d},null,8,["item"]))),128))])]),_:1},8,["label"])):f("",!0)}});const Xa=g(Ja,[["__scopeId","data-v-fdfb8e5a"]]),Za=s=>(z("data-v-57f83237"),s=s(),E(),s),Qa={class:"container"},er={class:"title"},tr={class:"content"},sr=Za(()=>c("div",{class:"curtain"},null,-1)),nr={class:"content-body"},or=m({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(s){const{y:e}=Le(),{hasSidebar:t}=D(),{frontmatter:n}=P(),o=L({});return we(()=>{o.value={"has-sidebar":t.value,top:n.value.layout==="home"&&e.value===0}}),(r,d)=>(a(),l("div",{class:C(["VPNavBar",o.value])},[c("div",Qa,[c("div",er,[h(Oa,null,{"nav-bar-title-before":v(()=>[u(r.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[u(r.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),c("div",tr,[sr,c("div",nr,[u(r.$slots,"nav-bar-content-before",{},void 0,!0),h(xa,{class:"search"}),h(La,{class:"menu"}),h(Xa,{class:"translations"}),h(bo,{class:"appearance"}),h(Ea,{class:"social-links"}),h(_a,{class:"extra"}),u(r.$slots,"nav-bar-content-after",{},void 0,!0),h(ga,{class:"hamburger",active:r.isScreenOpen,onClick:d[0]||(d[0]=p=>r.$emit("toggle-screen"))},null,8,["active"])])])])],2))}});const ar=g(or,[["__scopeId","data-v-57f83237"]]),rr={key:0,class:"VPNavScreenAppearance"},ir={class:"text"},lr=m({__name:"VPNavScreenAppearance",setup(s){const{site:e,theme:t}=P();return(n,o)=>i(e).appearance?(a(),l("div",rr,[c("p",ir,V(i(t).darkModeSwitchLabel||"Appearance"),1),h(me)])):f("",!0)}});const cr=g(lr,[["__scopeId","data-v-06a2ccf5"]]),ur=m({__name:"VPNavScreenMenuLink",props:{item:{}},setup(s){const e=oe("close-screen");return(t,n)=>(a(),$(O,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:v(()=>[H(V(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const dr=g(ur,[["__scopeId","data-v-8ff91e12"]]),_r={},vr={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},pr=c("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),hr=[pr];function fr(s,e){return a(),l("svg",vr,hr)}const mr=g(_r,[["render",fr]]),gr=m({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(s){const e=oe("close-screen");return(t,n)=>(a(),$(O,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:v(()=>[H(V(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const ze=g(gr,[["__scopeId","data-v-e7113d9e"]]),br={class:"VPNavScreenMenuGroupSection"},$r={key:0,class:"title"},kr=m({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),l("div",br,[e.text?(a(),l("p",$r,V(e.text),1)):f("",!0),(a(!0),l(M,null,B(e.items,n=>(a(),$(ze,{key:n.text,item:n},null,8,["item"]))),128))]))}});const yr=g(kr,[["__scopeId","data-v-f4e6c868"]]),Pr=["aria-controls","aria-expanded"],Vr={class:"button-text"},wr=["id"],Sr={key:1,class:"group"},Lr=m({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(s){const e=s,t=L(!1),n=y(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function o(){t.value=!t.value}return(r,d)=>(a(),l("div",{class:C(["VPNavScreenMenuGroup",{open:t.value}])},[c("button",{class:"button","aria-controls":n.value,"aria-expanded":t.value,onClick:o},[c("span",Vr,V(r.text),1),h(mr,{class:"button-icon"})],8,Pr),c("div",{id:n.value,class:"items"},[(a(!0),l(M,null,B(r.items,p=>(a(),l(M,{key:p.text},["link"in p?(a(),l("div",{key:p.text,class:"item"},[h(ze,{item:p},null,8,["item"])])):(a(),l("div",Sr,[h(yr,{text:p.text,items:p.items},null,8,["text","items"])]))],64))),128))],8,wr)],2))}});const Mr=g(Lr,[["__scopeId","data-v-13f80375"]]),Cr={key:0,class:"VPNavScreenMenu"},Nr=m({__name:"VPNavScreenMenu",setup(s){const{theme:e}=P();return(t,n)=>i(e).nav?(a(),l("nav",Cr,[(a(!0),l(M,null,B(i(e).nav,o=>(a(),l(M,{key:o.text},["link"in o?(a(),$(dr,{key:0,item:o},null,8,["item"])):(a(),$(Mr,{key:1,text:o.text||"",items:o.items},null,8,["text","items"]))],64))),128))])):f("",!0)}}),Ir=m({__name:"VPNavScreenSocialLinks",setup(s){const{theme:e}=P();return(t,n)=>i(e).socialLinks?(a(),$($e,{key:0,class:"VPNavScreenSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}}),Tr={class:"list"},Br=m({__name:"VPNavScreenTranslations",setup(s){const{localeLinks:e,currentLang:t}=X({correspondingLink:!0}),n=L(!1);function o(){n.value=!n.value}return(r,d)=>i(e).length&&i(t).label?(a(),l("div",{key:0,class:C(["VPNavScreenTranslations",{open:n.value}])},[c("button",{class:"title",onClick:o},[h(xe,{class:"icon lang"}),H(" "+V(i(t).label)+" ",1),h(He,{class:"icon chevron"})]),c("ul",Tr,[(a(!0),l(M,null,B(i(e),p=>(a(),l("li",{key:p.link,class:"item"},[h(O,{class:"link",href:p.link},{default:v(()=>[H(V(p.text),1)]),_:2},1032,["href"])]))),128))])],2)):f("",!0)}});const Ar=g(Br,[["__scopeId","data-v-84369744"]]),Hr={class:"container"},xr=m({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(s){const e=L(null),t=Me(q?document.body:null);return(n,o)=>(a(),$(ue,{name:"fade",onEnter:o[0]||(o[0]=r=>t.value=!0),onAfterLeave:o[1]||(o[1]=r=>t.value=!1)},{default:v(()=>[n.open?(a(),l("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[c("div",Hr,[u(n.$slots,"nav-screen-content-before",{},void 0,!0),h(Nr,{class:"menu"}),h(Ar,{class:"translations"}),h(cr,{class:"appearance"}),h(Ir,{class:"social-links"}),u(n.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):f("",!0)]),_:3}))}});const zr=g(xr,[["__scopeId","data-v-796c739a"]]),Er={key:0,class:"VPNav"},Dr=m({__name:"VPNav",setup(s){const{isScreenOpen:e,closeScreen:t,toggleScreen:n}=Jn(),{frontmatter:o}=P(),r=y(()=>o.value.navbar!==!1);return Ce("close-screen",t),se(()=>{q&&document.documentElement.classList.toggle("hide-nav",!r.value)}),(d,p)=>r.value?(a(),l("header",Er,[h(ar,{"is-screen-open":i(e),onToggleScreen:i(n)},{"nav-bar-title-before":v(()=>[u(d.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[u(d.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[u(d.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[u(d.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),h(zr,{open:i(e)},{"nav-screen-content-before":v(()=>[u(d.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[u(d.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):f("",!0)}});const Fr=g(Dr,[["__scopeId","data-v-ff202323"]]),Or=s=>(z("data-v-1b9f5c6f"),s=s(),E(),s),Gr=["role","tabindex"],Ur=Or(()=>c("div",{class:"indicator"},null,-1)),Rr=["onKeydown"],jr={key:1,class:"items"},qr=m({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(s){const e=s,{collapsed:t,collapsible:n,isLink:o,isActiveLink:r,hasActiveLink:d,hasChildren:p,toggle:_}=mt(y(()=>e.item)),k=y(()=>p.value?"section":"div"),N=y(()=>o.value?"a":"div"),T=y(()=>p.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),A=y(()=>o.value?void 0:"button"),I=y(()=>[[`level-${e.depth}`],{collapsible:n.value},{collapsed:t.value},{"is-link":o.value},{"is-active":r.value},{"has-active":d.value}]);function w(b){"key"in b&&b.key!=="Enter"||!e.item.link&&_()}function S(){e.item.link&&_()}return(b,x)=>{const Z=j("VPSidebarItem",!0);return a(),$(G(k.value),{class:C(["VPSidebarItem",I.value])},{default:v(()=>[b.item.text?(a(),l("div",Q({key:0,class:"item",role:A.value},We(b.item.items?{click:w,keydown:w}:{},!0),{tabindex:b.item.items&&0}),[Ur,b.item.link?(a(),$(O,{key:0,tag:N.value,class:"link",href:b.item.link,rel:b.item.rel,target:b.item.target},{default:v(()=>[(a(),$(G(T.value),{class:"text",innerHTML:b.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(a(),$(G(T.value),{key:1,class:"text",innerHTML:b.item.text},null,8,["innerHTML"])),b.item.collapsed!=null?(a(),l("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:S,onKeydown:Ye(S,["enter"]),tabindex:"0"},[h(fe,{class:"caret-icon"})],40,Rr)):f("",!0)],16,Gr)):f("",!0),b.item.items&&b.item.items.length?(a(),l("div",jr,[b.depth<5?(a(!0),l(M,{key:0},B(b.item.items,K=>(a(),$(Z,{key:K.text,item:K,depth:b.depth+1},null,8,["item","depth"]))),128)):f("",!0)])):f("",!0)]),_:1},8,["class"])}}});const Kr=g(qr,[["__scopeId","data-v-1b9f5c6f"]]),Ee=s=>(z("data-v-7ab77f34"),s=s(),E(),s),Wr=Ee(()=>c("div",{class:"curtain"},null,-1)),Yr={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},Jr=Ee(()=>c("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),Xr=m({__name:"VPSidebar",props:{open:{type:Boolean}},setup(s){const e=s,{sidebarGroups:t,hasSidebar:n}=D(),o=L(null),r=Me(q?document.body:null);return R([e,o],()=>{var d;e.open?(r.value=!0,(d=o.value)==null||d.focus()):r.value=!1},{immediate:!0,flush:"post"}),(d,p)=>i(n)?(a(),l("aside",{key:0,class:C(["VPSidebar",{open:d.open}]),ref_key:"navEl",ref:o,onClick:p[0]||(p[0]=Je(()=>{},["stop"]))},[Wr,c("nav",Yr,[Jr,u(d.$slots,"sidebar-nav-before",{},void 0,!0),(a(!0),l(M,null,B(i(t),_=>(a(),l("div",{key:_.text,class:"group"},[h(Kr,{item:_,depth:0},null,8,["item"])]))),128)),u(d.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):f("",!0)}});const Zr=g(Xr,[["__scopeId","data-v-7ab77f34"]]),Qr=m({__name:"VPSkipLink",setup(s){const e=ne(),t=L();R(()=>e.path,()=>t.value.focus());function n({target:o}){const r=document.getElementById(decodeURIComponent(o.hash).slice(1));if(r){const d=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",d)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",d),r.focus(),window.scrollTo(0,0)}}return(o,r)=>(a(),l(M,null,[c("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),c("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:n}," Skip to content ")],64))}});const ei=g(Qr,[["__scopeId","data-v-315fcc9b"]]),ti=m({__name:"Layout",setup(s){const{isOpen:e,open:t,close:n}=D(),o=ne();R(()=>o.path,n),ft(e,n);const{frontmatter:r}=P(),d=Xe(),p=y(()=>!!d["home-hero-image"]);return Ce("hero-image-slot-exists",p),(_,k)=>{const N=j("Content");return i(r).layout!==!1?(a(),l("div",{key:0,class:C(["Layout",i(r).pageClass])},[u(_.$slots,"layout-top",{},void 0,!0),h(ei),h(st,{class:"backdrop",show:i(e),onClick:i(n)},null,8,["show","onClick"]),h(Fr,null,{"nav-bar-title-before":v(()=>[u(_.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[u(_.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[u(_.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[u(_.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":v(()=>[u(_.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[u(_.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),h(Yn,{open:i(e),onOpenMenu:i(t)},null,8,["open","onOpenMenu"]),h(Zr,{open:i(e)},{"sidebar-nav-before":v(()=>[u(_.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":v(()=>[u(_.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),h(Ln,null,{"page-top":v(()=>[u(_.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[u(_.$slots,"page-bottom",{},void 0,!0)]),"not-found":v(()=>[u(_.$slots,"not-found",{},void 0,!0)]),"home-hero-before":v(()=>[u(_.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[u(_.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[u(_.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[u(_.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[u(_.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[u(_.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":v(()=>[u(_.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[u(_.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[u(_.$slots,"doc-after",{},void 0,!0)]),"doc-top":v(()=>[u(_.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[u(_.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":v(()=>[u(_.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[u(_.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[u(_.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[u(_.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[u(_.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[u(_.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),h(Tn),u(_.$slots,"layout-bottom",{},void 0,!0)],2)):(a(),$(N,{key:1}))}}});const si=g(ti,[["__scopeId","data-v-f6284a77"]]),ni={xmini:[[0,2]],mini:[],small:[[920,6],[768,5],[640,4],[480,3],[0,2]],medium:[[960,5],[832,4],[640,3],[480,2]],big:[[832,3],[640,2]]};function oi({el:s,size:e="medium"}){const t=Ne(n,100);F(()=>{n(),window.addEventListener("resize",t)}),J(()=>{window.removeEventListener("resize",t)});function n(){ai(s.value,e)}}function ai(s,e){const t=s.children.length,n=s.querySelectorAll(".vp-sponsor-grid-item:not(.empty)").length,o=ri(s,e,n);li(s,o,t,n)}function ri(s,e,t){const n=ni[e],o=window.innerWidth;let r=1;return n.some(([d,p])=>{if(o>=d)return r=t0?ui(s,e):di(s,e*-1))}function ui(s,e){for(let t=0;t(a(),l("div",{class:C(["VPSponsorsGrid vp-sponsor-grid",[n.size]]),ref_key:"el",ref:t},[(a(!0),l(M,null,B(n.data,r=>(a(),l("div",{key:r.name,class:"vp-sponsor-grid-item"},[c("a",{class:"vp-sponsor-grid-link",href:r.url,target:"_blank",rel:"sponsored noopener"},[c("article",vi,[c("h4",pi,V(r.name),1),c("img",{class:"vp-sponsor-grid-image",src:r.img,alt:r.name},null,8,hi)])],8,_i)]))),128))],2))}}),mi={key:0,class:"vp-sponsor-tier"},gi=m({__name:"VPSponsors",props:{mode:{default:"normal"},tier:{},size:{},data:{}},setup(s){const e=s,t=y(()=>e.data.some(o=>"items"in o)?e.data:[{tier:e.tier,size:e.size,items:e.data}]);return(n,o)=>(a(),l("div",{class:C(["VPSponsors vp-sponsor",[n.mode]])},[(a(!0),l(M,null,B(t.value,(r,d)=>(a(),l("section",{key:d,class:"vp-sponsor-section"},[r.tier?(a(),l("h3",mi,V(r.tier),1)):f("",!0),h(fi,{size:r.size,data:r.items},null,8,["size","data"])]))),128))],2))}});const bi={class:"VPDocAsideSponsors"},ki=m({__name:"VPDocAsideSponsors",props:{tier:{},size:{},data:{}},setup(s){return(e,t)=>(a(),l("div",bi,[h(gi,{mode:"aside",tier:e.tier,size:e.size,data:e.data},null,8,["tier","size","data"])]))}});const yi={Layout:si,enhanceApp:({app:s})=>{s.component("Badge",Qe)}};export{ki as _,yi as t,P as u}; diff --git a/assets/development_aws_acknowledgement.md.daba60ba.js b/assets/development_aws_acknowledgement.md.ebd64504.js similarity index 97% rename from assets/development_aws_acknowledgement.md.daba60ba.js rename to assets/development_aws_acknowledgement.md.ebd64504.js index 1d3ee889..84cfc5cb 100644 --- a/assets/development_aws_acknowledgement.md.daba60ba.js +++ b/assets/development_aws_acknowledgement.md.ebd64504.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o,c as s,H as n,k as e,a as l,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"謝辞","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/acknowledgement.md","filePath":"development/aws/acknowledgement.md","lastUpdated":1695377563000}'),p={name:"development/aws/acknowledgement.md"},c=e("h1",{id:"謝辞",tabindex:"-1"},[l("謝辞 "),e("a",{class:"header-anchor",href:"#謝辞","aria-label":'Permalink to "謝辞"'},"​")],-1),_=i('

    本原稿の執筆にあたり,以下の方々からの協力を得た.この場を借りて,感謝を表したい.

    2021 年バージョンの contributors

    • 香取真知子氏 - ハンズオンプログラムの動作確認,文章校閲

    2020 年バージョンの contributors

    • 勝俣敬寛氏 - Docker イメージの作成

    • 香取真知子氏 - ハンズオンプログラムの動作確認

    • @shuuji3 - MR !15

    • @takatama_jp - MR !14

    本書の執筆には Asciidoctor を使用した.

    また,本書はオープンソースの教科書として,すべての読者・ディベロッパーからのフィードバックを受け付けている. 誤植や記述の誤り,改善点など見つかったら,ぜひ IssuesPull request を投稿していただきたい.

    ',7);function m(d,h,f,g,k,u){const t=a;return o(),s("div",null,[c,n(t,{readTime:"1",words:"129"}),_])}const N=r(p,[["render",m]]);export{P as __pageData,N as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o,c as s,H as n,k as e,a as l,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"謝辞","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/acknowledgement.md","filePath":"development/aws/acknowledgement.md","lastUpdated":1699051935000}'),p={name:"development/aws/acknowledgement.md"},c=e("h1",{id:"謝辞",tabindex:"-1"},[l("謝辞 "),e("a",{class:"header-anchor",href:"#謝辞","aria-label":'Permalink to "謝辞"'},"​")],-1),_=i('

    本原稿の執筆にあたり,以下の方々からの協力を得た.この場を借りて,感謝を表したい.

    2021 年バージョンの contributors

    • 香取真知子氏 - ハンズオンプログラムの動作確認,文章校閲

    2020 年バージョンの contributors

    • 勝俣敬寛氏 - Docker イメージの作成

    • 香取真知子氏 - ハンズオンプログラムの動作確認

    • @shuuji3 - MR !15

    • @takatama_jp - MR !14

    本書の執筆には Asciidoctor を使用した.

    また,本書はオープンソースの教科書として,すべての読者・ディベロッパーからのフィードバックを受け付けている. 誤植や記述の誤り,改善点など見つかったら,ぜひ IssuesPull request を投稿していただきたい.

    ',7);function m(d,h,f,g,k,u){const t=a;return o(),s("div",null,[c,n(t,{readTime:"1",words:"129"}),_])}const N=r(p,[["render",m]]);export{P as __pageData,N as default}; diff --git a/assets/development_aws_acknowledgement.md.daba60ba.lean.js b/assets/development_aws_acknowledgement.md.ebd64504.lean.js similarity index 91% rename from assets/development_aws_acknowledgement.md.daba60ba.lean.js rename to assets/development_aws_acknowledgement.md.ebd64504.lean.js index 47d1977c..87e53cbe 100644 --- a/assets/development_aws_acknowledgement.md.daba60ba.lean.js +++ b/assets/development_aws_acknowledgement.md.ebd64504.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o,c as s,H as n,k as e,a as l,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"謝辞","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/acknowledgement.md","filePath":"development/aws/acknowledgement.md","lastUpdated":1695377563000}'),p={name:"development/aws/acknowledgement.md"},c=e("h1",{id:"謝辞",tabindex:"-1"},[l("謝辞 "),e("a",{class:"header-anchor",href:"#謝辞","aria-label":'Permalink to "謝辞"'},"​")],-1),_=i("",7);function m(d,h,f,g,k,u){const t=a;return o(),s("div",null,[c,n(t,{readTime:"1",words:"129"}),_])}const N=r(p,[["render",m]]);export{P as __pageData,N as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o,c as s,H as n,k as e,a as l,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"謝辞","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/acknowledgement.md","filePath":"development/aws/acknowledgement.md","lastUpdated":1699051935000}'),p={name:"development/aws/acknowledgement.md"},c=e("h1",{id:"謝辞",tabindex:"-1"},[l("謝辞 "),e("a",{class:"header-anchor",href:"#謝辞","aria-label":'Permalink to "謝辞"'},"​")],-1),_=i("",7);function m(d,h,f,g,k,u){const t=a;return o(),s("div",null,[c,n(t,{readTime:"1",words:"129"}),_])}const N=r(p,[["render",m]]);export{P as __pageData,N as default}; diff --git a/assets/development_aws_appendix.md.071021e4.js b/assets/development_aws_appendix.md.071021e4.js new file mode 100644 index 00000000..5c0c9275 --- /dev/null +++ b/assets/development_aws_appendix.md.071021e4.js @@ -0,0 +1,29 @@ +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,a as p,b as o,c as l,d as r,e as c,f as t,g as i,h as d,i as y,j as u,k as h,l as m,m as F,n as A,o as g}from"./chunks/venv_shell.dc2530bc.js";import{_ as b,o as C,c as D,H as v,k as s,a as k,Q as f}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const K=JSON.parse('{"title":"Appendix: 環境構築","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/appendix.md","filePath":"development/aws/appendix.md","lastUpdated":1699051935000}'),_={name:"development/aws/appendix.md"},w=s("h1",{id:"appendix-環境構築",tabindex:"-1"},[k("Appendix: 環境構築 "),s("a",{class:"header-anchor",href:"#appendix-環境構築","aria-label":'Permalink to "Appendix: 環境構築"'},"​")],-1),S=f('

    本書を読み進めるにあたって,ハンズオンのプログラムを実行するための環境を自分のローカルマシンにセットアップしなければならない. ここでは, AWS やコマンドラインの初心者を想定して,本章で必要なソフトウェアやライブラリのインストールなどを簡単に解説する. 以下に簡単な目次を示そう. 既に環境構築が済んでいる場合は適宜読み飛ばしていただき,関係のある箇所のみ目を通せば良い.

    使用する OS は Linux/Mac/Windows のどれを用いても構わない. Windows のユーザーは, Windows Subsytem for Linux (WSL) を使用することを想定している (WSL のインストール).

    また,本書のハンズオンを実行するための Docker イメージ を提供している. これを用いると, AWS CLI/CDK や Python の設定などをスキップできるので, Docker の使用方法を知っている読者には便利だろう.

    AWS アカウントの取得

    本書で提供するハンズオンを実際に自分で試すには,読者自身で AWS のアカウントの作成をする必要がある. 詳しいアカウントの作成の手順は 公式のドキュメンテーション に書かれているので,そちらも参照していただきたい. 以下の手順に従ってアカウントの作成を行う.

    まず,ウェブブラウザから AWS コンソール にアクセスし,右上の Create an AWS Account をクリックする (figure_title で実線で囲った部分).

    サインアップ (1): AWS コンソールにアクセス

    次に,遷移した先のページでメールアドレスとパスワードなどの登録を行う (figure_title).

    サインアップ (2): メールアドレス・パスワードなどの登録.

    続いて,住所や電話番号などを訊かれるので,すべて入力しよう (figure_title).

    サインアップ (3): 住所・電話番号の入力

    次に,クレジットカードの情報の登録を求められる (figure_title). 個人で AWS を利用する場合は,利用料金の請求はクレジットカードを経由して行われる. クレジットカードの登録なしには AWS を使い始めることはできないことに注意.

    サインアップ (4): クレジットカードの登録

    次の画面では,携帯電話の SMS またはボイスメッセージを利用した本人確認が求められる (figure_title). 希望の認証方法を選択し,自分の携帯電話番号を入力しよう.

    サインアップ (5): 携帯電話による本人確認

    無事に本人確認が完了すると,最後にサポートプランの選択を求められる (figure_title). 無料の Basic support を選択しておけば問題ない.

    サインアップ (6): サポートプランの選択

    以上のステップにより,アカウントの作成が完了する (figure_title). 早速ログインをして, AWS コンソールにアクセスできるか確認しておこう.

    サインアップ (7): アカウントの作成が完了した

    AWS のシークレットキーの作成

    AWS シークレットキーとは, AWS CLI や AWS CDK から AWS の API を操作するときに,ユーザー認証を行うための鍵のことである. AWS CLI/CDK を使うには,最初にシークレットキーを発行する必要がある. AWS シークレットキーの詳細は 公式ドキュメンテーション "Understanding and getting your AWS credentials" を参照.

    1. AWS コンソールにログインする.

    2. 画面右上のアカウント名をクリックし,表示されるプルダウンメニューから "My Security Credentials" を選択 (figure_title)

    3. "Access keys for CLI, SDK, & API access" の下にある "Create accesss key" のボタンをクリックする (figure_title)

    4. 表示された Access key ID, Secret access key を記録しておく (画面を閉じると二度と表示されない).

    5. 鍵を忘れてしまった場合などは,同じ手順で再発行が可能である.

    6. 発行したシークレットキーは, ~/.aws/credentials のファイルに書き込むか,環境変数に設定するなどして使う (詳しくは AWS CLI のインストール).

    AWS シークレットキーの発行1

    AWS シークレットキーの発行2

    AWS Educate Starter Account を用いている場合は,次の手順でシークレットキーを確認する.

    • AWS Educate のコンソール画面から, vocareum のコンソールに移動する (figure_title).

    • Account Details をクリックし,続いて AWS CLI: Show をクリックする.

    • aws_access_key_id, aws_secret_access_key, aws_session_token が表示される (figure_title). ここで表示された内容を ~/.aws/credentials にコピーする (AWS CLI のインストール 参照). aws_session_token の箇所も漏らさずコピーすること.

    • 続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

    toml
    [default]
    +    region = us-east-1
    +    output = json
    [default]
    +    region = us-east-1
    +    output = json
    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).

    vocareum コンソール

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    sh
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    本書のハンズオンではコマンドラインから AWS CLI のコマンドを実行したり, Python で書かれたプログラムを実行する. コマンドは基本的に UNIX のターミナルを想定して書かれている. Linux や Mac のユーザーは OS に標準搭載されているターミナルを用いれば良い. Windows を利用している読者は, Windows Subsystem for Linux (WSL) を利用することで,仮想の Linux 環境を構築することを推奨する. Cygwin などの Linux 環境をエミュレートするほかのツールでも構わないが,本書のプログラムは WSL でのみ動作確認を行っている.

    WSL とは, Windows の OS 上で Linux の仮想環境を起動するための, Microsoft 社が公式で提供しているソフトウェアである. Ubuntu など希望の Linux distribution が選択でき,基本的にすべての Linux 向けに作られたプログラム・ソフトウェアを使用することができる.

    執筆時点では WSL 2 が最新版として提供されているので,以下では WSL 2 のインストール手順を簡単に説明する. 細かな詳細などは, 公式ドキュメンテーション を参照のこと.

    前提として,使用される OS は Windows 10 (Pro または Home エディション) でなければならない. さらに,使用している Windows 10 のバージョンが WSL に対応するバージョンであるかを確認する. X64 のシステムでは Version 1903, Build 18362 以上でなければならない. バージョンが対応していない場合は、 Windows のアップデートを行う.

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    powershell
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    powershell
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    Ubuntu 20.04 を初回に起動すると,初期設定が自動で開始され,数分待つことになる. 初期設定が終わると,ユーザー名・パスワードを設定するようプロンプトが出るので,プロンプトに従い入力する.

    これで WSL2 のインストールが完了した. 早速 WSL2 を起動してみよう. 左下の Windows メニューの検索バーに Ubuntu と入力すると, Ubuntu 20.04 のプログラムが見つかるはずである (figure_title). クリックして起動しよう.

    Ubuntu 20.04 の起動

    すると,ターミナルの黒い画面が立ち上がるだろう (figure_title). ls, top などのコマンドを打ってみて, WSL がきちんと動作していることを確認しよう.

    WSL の起動画面

    オプションとして, Windows Terminal というマイクロソフトから提供されているツールを使うと,より快適に WSL を使用することができる. 興味のある読者はこちらのインストールも推奨する.

    Docker のインストール

    Docker のインストールの方法は OS によって異なる.

    Mac ユーザーは, Docker Desktop をインストールする. インストールの方法は, Docker のウェブサイト から, Mac 版の Docker Desktop をダウンロードし,ダウンロードされたファイルをダブルクリックし, Applications のフォルダにドラッグするだけで良い. 詳細は 公式ドキュメンテーション を参照のこと.

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh\n$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh\n$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    ハンズオンを実行するために必要な, Node.js, Python, AWS CDK などがインストールされた Docker image を用意した. これを使用することで,自分のローカルマシンに諸々をインストールする必要なく,すぐにハンズオンのコードが実行できる.

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    root@aws-handson:~$</programlisting>

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい ( (#sec_handson_ec2_run) など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    ',140);function E(B,W,x,L,$,Y){const a=e;return C(),D("div",null,[w,v(a,{readTime:"9",words:"2.3k"}),S])}const U=b(_,[["render",E]]);export{K as __pageData,U as default}; diff --git a/assets/development_aws_appendix.md.071021e4.lean.js b/assets/development_aws_appendix.md.071021e4.lean.js new file mode 100644 index 00000000..2383b812 --- /dev/null +++ b/assets/development_aws_appendix.md.071021e4.lean.js @@ -0,0 +1 @@ +import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,a as p,b as o,c as l,d as r,e as c,f as t,g as i,h as d,i as y,j as u,k as h,l as m,m as F,n as A,o as g}from"./chunks/venv_shell.dc2530bc.js";import{_ as b,o as C,c as D,H as v,k as s,a as k,Q as f}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const K=JSON.parse('{"title":"Appendix: 環境構築","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/appendix.md","filePath":"development/aws/appendix.md","lastUpdated":1699051935000}'),_={name:"development/aws/appendix.md"},w=s("h1",{id:"appendix-環境構築",tabindex:"-1"},[k("Appendix: 環境構築 "),s("a",{class:"header-anchor",href:"#appendix-環境構築","aria-label":'Permalink to "Appendix: 環境構築"'},"​")],-1),S=f("",140);function E(B,W,x,L,$,Y){const a=e;return C(),D("div",null,[w,v(a,{readTime:"9",words:"2.3k"}),S])}const U=b(_,[["render",E]]);export{K as __pageData,U as default}; diff --git a/assets/development_aws_appendix.md.568c3e80.js b/assets/development_aws_appendix.md.568c3e80.js deleted file mode 100644 index 1f6e29e8..00000000 --- a/assets/development_aws_appendix.md.568c3e80.js +++ /dev/null @@ -1,29 +0,0 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,a as o,b as l,c as p,d as r,e as c,f as t,g as i,h as d,i as y,j as u,k as h,l as A,m,n as g,o as b}from"./chunks/venv_shell.dc2530bc.js";import{_ as v,o as B,c as k,H as f,k as s,a as _,Q as w}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const K=JSON.parse('{"title":"Appendix: 環境構築","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/appendix.md","filePath":"development/aws/appendix.md","lastUpdated":1695377563000}'),S={name:"development/aws/appendix.md"},D=s("h1",{id:"appendix-環境構築",tabindex:"-1"},[_("Appendix: 環境構築 "),s("a",{class:"header-anchor",href:"#appendix-環境構築","aria-label":'Permalink to "Appendix: 環境構築"'},"​")],-1),C=w('

    本書を読み進めるにあたって,ハンズオンのプログラムを実行するための環境を自分のローカルマシンにセットアップしなければならない. ここでは, AWS やコマンドラインの初心者を想定して,本章で必要なソフトウェアやライブラリのインストールなどを簡単に解説する. 以下に簡単な目次を示そう. 既に環境構築が済んでいる場合は適宜読み飛ばしていただき,関係のある箇所のみ目を通せば良い.

    使用する OS は Linux/Mac/Windows のどれを用いても構わない. Windows のユーザーは, Windows Subsytem for Linux (WSL) を使用することを想定している (WSL のインストール).

    また,本書のハンズオンを実行するための Docker イメージ を提供している. これを用いると, AWS CLI/CDK や Python の設定などをスキップできるので, Docker の使用方法を知っている読者には便利だろう.

    AWS アカウントの取得

    本書で提供するハンズオンを実際に自分で試すには,読者自身で AWS のアカウントの作成をする必要がある. 詳しいアカウントの作成の手順は 公式のドキュメンテーション に書かれているので,そちらも参照していただきたい. 以下の手順に従ってアカウントの作成を行う.

    まず,ウェブブラウザから AWS コンソール にアクセスし,右上の Create an AWS Account をクリックする (figure_title で実線で囲った部分).

    サインアップ (1): AWS コンソールにアクセス

    次に,遷移した先のページでメールアドレスとパスワードなどの登録を行う (figure_title).

    サインアップ (2): メールアドレス・パスワードなどの登録.

    続いて,住所や電話番号などを訊かれるので,すべて入力しよう (figure_title).

    サインアップ (3): 住所・電話番号の入力

    次に,クレジットカードの情報の登録を求められる (figure_title). 個人で AWS を利用する場合は,利用料金の請求はクレジットカードを経由して行われる. クレジットカードの登録なしには AWS を使い始めることはできないことに注意.

    サインアップ (4): クレジットカードの登録

    次の画面では,携帯電話の SMS またはボイスメッセージを利用した本人確認が求められる (figure_title). 希望の認証方法を選択し,自分の携帯電話番号を入力しよう.

    サインアップ (5): 携帯電話による本人確認

    無事に本人確認が完了すると,最後にサポートプランの選択を求められる (figure_title). 無料の Basic support を選択しておけば問題ない.

    サインアップ (6): サポートプランの選択

    以上のステップにより,アカウントの作成が完了する (figure_title). 早速ログインをして, AWS コンソールにアクセスできるか確認しておこう.

    サインアップ (7): アカウントの作成が完了した

    AWS のシークレットキーの作成

    AWS シークレットキーとは, AWS CLI や AWS CDK から AWS の API を操作するときに,ユーザー認証を行うための鍵のことである. AWS CLI/CDK を使うには,最初にシークレットキーを発行する必要がある. AWS シークレットキーの詳細は 公式ドキュメンテーション "Understanding and getting your AWS credentials" を参照.

    1. AWS コンソールにログインする.

    2. 画面右上のアカウント名をクリックし,表示されるプルダウンメニューから "My Security Credentials" を選択 (figure_title)

    3. "Access keys for CLI, SDK, & API access" の下にある "Create accesss key" のボタンをクリックする (figure_title)

    4. 表示された Access key ID, Secret access key を記録しておく (画面を閉じると二度と表示されない).

    5. 鍵を忘れてしまった場合などは,同じ手順で再発行が可能である.

    6. 発行したシークレットキーは, ~/.aws/credentials のファイルに書き込むか,環境変数に設定するなどして使う (詳しくは AWS CLI のインストール).

    AWS シークレットキーの発行1

    AWS シークレットキーの発行2

    AWS Educate Starter Account を用いている場合は,次の手順でシークレットキーを確認する.

    • AWS Educate のコンソール画面から, vocareum のコンソールに移動する (figure_title).

    • Account Details をクリックし,続いて AWS CLI: Show をクリックする.

    • aws_access_key_id, aws_secret_access_key, aws_session_token が表示される (figure_title). ここで表示された内容を ~/.aws/credentials にコピーする (AWS CLI のインストール 参照). aws_session_token の箇所も漏らさずコピーすること.

    • 続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

    toml
    [default]
    -    region = us-east-1
    -    output = json
    [default]
    -    region = us-east-1
    -    output = json
    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).

    vocareum コンソール

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    sh
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    -
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    -
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    本書のハンズオンではコマンドラインから AWS CLI のコマンドを実行したり, Python で書かれたプログラムを実行する. コマンドは基本的に UNIX のターミナルを想定して書かれている. Linux や Mac のユーザーは OS に標準搭載されているターミナルを用いれば良い. Windows を利用している読者は, Windows Subsystem for Linux (WSL) を利用することで,仮想の Linux 環境を構築することを推奨する. Cygwin などの Linux 環境をエミュレートするほかのツールでも構わないが,本書のプログラムは WSL でのみ動作確認を行っている.

    WSL とは, Windows の OS 上で Linux の仮想環境を起動するための, Microsoft 社が公式で提供しているソフトウェアである. Ubuntu など希望の Linux distribution が選択でき,基本的にすべての Linux 向けに作られたプログラム・ソフトウェアを使用することができる.

    執筆時点では WSL 2 が最新版として提供されているので,以下では WSL 2 のインストール手順を簡単に説明する. 細かな詳細などは, 公式ドキュメンテーション を参照のこと.

    前提として,使用される OS は Windows 10 (Pro または Home エディション) でなければならない. さらに,使用している Windows 10 のバージョンが WSL に対応するバージョンであるかを確認する. X64 のシステムでは Version 1903, Build 18362 以上でなければならない. バージョンが対応していない場合は、 Windows のアップデートを行う.

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    powershell
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    powershell
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    Ubuntu 20.04 を初回に起動すると,初期設定が自動で開始され,数分待つことになる. 初期設定が終わると,ユーザー名・パスワードを設定するようプロンプトが出るので,プロンプトに従い入力する.

    これで WSL2 のインストールが完了した. 早速 WSL2 を起動してみよう. 左下の Windows メニューの検索バーに Ubuntu と入力すると, Ubuntu 20.04 のプログラムが見つかるはずである (figure_title). クリックして起動しよう.

    Ubuntu 20.04 の起動

    すると,ターミナルの黒い画面が立ち上がるだろう (figure_title). ls, top などのコマンドを打ってみて, WSL がきちんと動作していることを確認しよう.

    WSL の起動画面

    オプションとして, Windows Terminal というマイクロソフトから提供されているツールを使うと,より快適に WSL を使用することができる. 興味のある読者はこちらのインストールも推奨する.

    Docker のインストール

    Docker のインストールの方法は OS によって異なる.

    Mac ユーザーは, Docker Desktop をインストールする. インストールの方法は, Docker のウェブサイト から, Mac 版の Docker Desktop をダウンロードし,ダウンロードされたファイルをダブルクリックし, Applications のフォルダにドラッグするだけで良い. 詳細は 公式ドキュメンテーション を参照のこと.

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh\n$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh\n$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    ハンズオンを実行するために必要な, Node.js, Python, AWS CDK などがインストールされた Docker image を用意した. これを使用することで,自分のローカルマシンに諸々をインストールする必要なく,すぐにハンズオンのコードが実行できる.

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    root@aws-handson:~$</programlisting>

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい ( (#sec_handson_ec2_run) など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    ',140);function W(z,x,L,$,Y,X){const a=e;return B(),k("div",null,[D,f(a,{readTime:"9",words:"2.3k"}),C])}const U=v(S,[["render",W]]);export{K as __pageData,U as default}; diff --git a/assets/development_aws_appendix.md.568c3e80.lean.js b/assets/development_aws_appendix.md.568c3e80.lean.js deleted file mode 100644 index 6e8ddf9b..00000000 --- a/assets/development_aws_appendix.md.568c3e80.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,a as o,b as l,c as p,d as r,e as c,f as t,g as i,h as d,i as y,j as u,k as h,l as A,m,n as g,o as b}from"./chunks/venv_shell.dc2530bc.js";import{_ as v,o as B,c as k,H as f,k as s,a as _,Q as w}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const K=JSON.parse('{"title":"Appendix: 環境構築","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/appendix.md","filePath":"development/aws/appendix.md","lastUpdated":1695377563000}'),S={name:"development/aws/appendix.md"},D=s("h1",{id:"appendix-環境構築",tabindex:"-1"},[_("Appendix: 環境構築 "),s("a",{class:"header-anchor",href:"#appendix-環境構築","aria-label":'Permalink to "Appendix: 環境構築"'},"​")],-1),C=w("",140);function W(z,x,L,$,Y,X){const a=e;return B(),k("div",null,[D,f(a,{readTime:"9",words:"2.3k"}),C])}const U=v(S,[["render",W]]);export{K as __pageData,U as default}; diff --git a/assets/development_aws_assignments.md.35fe9703.js b/assets/development_aws_assignments.md.fcb27d2d.js similarity index 92% rename from assets/development_aws_assignments.md.35fe9703.js rename to assets/development_aws_assignments.md.fcb27d2d.js index dddf9963..d6f2f17c 100644 --- a/assets/development_aws_assignments.md.35fe9703.js +++ b/assets/development_aws_assignments.md.fcb27d2d.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as s,o as n,c as o,H as r,k as e,a as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"課題","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/assignments.md","filePath":"development/aws/assignments.md","lastUpdated":1695377563000}'),d={name:"development/aws/assignments.md"},i=e("h1",{id:"課題",tabindex:"-1"},[c("課題 "),e("a",{class:"header-anchor",href:"#課題","aria-label":'Permalink to "課題"'},"​")],-1),m=e("p",null,"以下の課題を提出.",-1);function _(l,p,f,h,g,u){const a=t;return n(),o("div",null,[i,r(a,{readTime:"1",words:"8"}),m])}const w=s(d,[["render",_]]);export{k as __pageData,w as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as s,o as n,c as o,H as r,k as e,a as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"課題","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/assignments.md","filePath":"development/aws/assignments.md","lastUpdated":1699051935000}'),d={name:"development/aws/assignments.md"},i=e("h1",{id:"課題",tabindex:"-1"},[c("課題 "),e("a",{class:"header-anchor",href:"#課題","aria-label":'Permalink to "課題"'},"​")],-1),m=e("p",null,"以下の課題を提出.",-1);function _(l,p,f,h,g,u){const a=t;return n(),o("div",null,[i,r(a,{readTime:"1",words:"8"}),m])}const w=s(d,[["render",_]]);export{k as __pageData,w as default}; diff --git a/assets/development_aws_assignments.md.35fe9703.lean.js b/assets/development_aws_assignments.md.fcb27d2d.lean.js similarity index 92% rename from assets/development_aws_assignments.md.35fe9703.lean.js rename to assets/development_aws_assignments.md.fcb27d2d.lean.js index dddf9963..d6f2f17c 100644 --- a/assets/development_aws_assignments.md.35fe9703.lean.js +++ b/assets/development_aws_assignments.md.fcb27d2d.lean.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as s,o as n,c as o,H as r,k as e,a as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"課題","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/assignments.md","filePath":"development/aws/assignments.md","lastUpdated":1695377563000}'),d={name:"development/aws/assignments.md"},i=e("h1",{id:"課題",tabindex:"-1"},[c("課題 "),e("a",{class:"header-anchor",href:"#課題","aria-label":'Permalink to "課題"'},"​")],-1),m=e("p",null,"以下の課題を提出.",-1);function _(l,p,f,h,g,u){const a=t;return n(),o("div",null,[i,r(a,{readTime:"1",words:"8"}),m])}const w=s(d,[["render",_]]);export{k as __pageData,w as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as s,o as n,c as o,H as r,k as e,a as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"課題","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/assignments.md","filePath":"development/aws/assignments.md","lastUpdated":1699051935000}'),d={name:"development/aws/assignments.md"},i=e("h1",{id:"課題",tabindex:"-1"},[c("課題 "),e("a",{class:"header-anchor",href:"#課題","aria-label":'Permalink to "課題"'},"​")],-1),m=e("p",null,"以下の課題を提出.",-1);function _(l,p,f,h,g,u){const a=t;return n(),o("div",null,[i,r(a,{readTime:"1",words:"8"}),m])}const w=s(d,[["render",_]]);export{k as __pageData,w as default}; diff --git a/assets/development_aws_author.md.025b6bde.js b/assets/development_aws_author.md.a292956b.js similarity index 95% rename from assets/development_aws_author.md.025b6bde.js rename to assets/development_aws_author.md.a292956b.js index ca4b4f06..1b64e10e 100644 --- a/assets/development_aws_author.md.025b6bde.js +++ b/assets/development_aws_author.md.a292956b.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o as n,c as s,H as m,k as e,a as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"著者紹介","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/author.md","filePath":"development/aws/author.md","lastUpdated":1695377563000}'),c={name:"development/aws/author.md"},i=e("h1",{id:"著者紹介",tabindex:"-1"},[t("著者紹介 "),e("a",{class:"header-anchor",href:"#著者紹介","aria-label":'Permalink to "著者紹介"'},"​")],-1),l=e("p",null,"真野 智之 (Tomoyuki Mano)",-1),d=e("p",null,"情報理工学博士 (東京大学大学院情報理工学系研究科システム情報学専攻). 2021 年より日本学術振興会特別研究員 (PD) (現職). 沖縄科学技術大学院大学 (OIST) にてポスドク研究員として働く. 現在の研究分野は神経科学・神経情報学. 趣味は料理・ランニング・鉄道・アニメ,村上春樹の熱烈な愛読家.",-1),_=e("p",null,[t("連絡先 "),e("a",{href:"mailto:tomoyukimano@gmail.com",target:"_blank",rel:"noreferrer"},"tomoyukimano@gmail.com")],-1),p=e("p",null,[t("GitHub "),e("a",{href:"https://github.com/tomomano",target:"_blank",rel:"noreferrer"},"https://github.com/tomomano")],-1);function h(u,f,k,g,b,v){const o=a;return n(),s("div",null,[i,m(o,{readTime:"1",words:"110"}),l,d,_,p])}const N=r(c,[["render",h]]);export{w as __pageData,N as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o as n,c as s,H as m,k as e,a as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"著者紹介","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/author.md","filePath":"development/aws/author.md","lastUpdated":1699051935000}'),c={name:"development/aws/author.md"},i=e("h1",{id:"著者紹介",tabindex:"-1"},[t("著者紹介 "),e("a",{class:"header-anchor",href:"#著者紹介","aria-label":'Permalink to "著者紹介"'},"​")],-1),l=e("p",null,"真野 智之 (Tomoyuki Mano)",-1),d=e("p",null,"情報理工学博士 (東京大学大学院情報理工学系研究科システム情報学専攻). 2021 年より日本学術振興会特別研究員 (PD) (現職). 沖縄科学技術大学院大学 (OIST) にてポスドク研究員として働く. 現在の研究分野は神経科学・神経情報学. 趣味は料理・ランニング・鉄道・アニメ,村上春樹の熱烈な愛読家.",-1),_=e("p",null,[t("連絡先 "),e("a",{href:"mailto:tomoyukimano@gmail.com",target:"_blank",rel:"noreferrer"},"tomoyukimano@gmail.com")],-1),p=e("p",null,[t("GitHub "),e("a",{href:"https://github.com/tomomano",target:"_blank",rel:"noreferrer"},"https://github.com/tomomano")],-1);function h(u,f,k,g,b,v){const o=a;return n(),s("div",null,[i,m(o,{readTime:"1",words:"110"}),l,d,_,p])}const N=r(c,[["render",h]]);export{w as __pageData,N as default}; diff --git a/assets/development_aws_author.md.025b6bde.lean.js b/assets/development_aws_author.md.a292956b.lean.js similarity index 95% rename from assets/development_aws_author.md.025b6bde.lean.js rename to assets/development_aws_author.md.a292956b.lean.js index ca4b4f06..1b64e10e 100644 --- a/assets/development_aws_author.md.025b6bde.lean.js +++ b/assets/development_aws_author.md.a292956b.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o as n,c as s,H as m,k as e,a as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"著者紹介","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/author.md","filePath":"development/aws/author.md","lastUpdated":1695377563000}'),c={name:"development/aws/author.md"},i=e("h1",{id:"著者紹介",tabindex:"-1"},[t("著者紹介 "),e("a",{class:"header-anchor",href:"#著者紹介","aria-label":'Permalink to "著者紹介"'},"​")],-1),l=e("p",null,"真野 智之 (Tomoyuki Mano)",-1),d=e("p",null,"情報理工学博士 (東京大学大学院情報理工学系研究科システム情報学専攻). 2021 年より日本学術振興会特別研究員 (PD) (現職). 沖縄科学技術大学院大学 (OIST) にてポスドク研究員として働く. 現在の研究分野は神経科学・神経情報学. 趣味は料理・ランニング・鉄道・アニメ,村上春樹の熱烈な愛読家.",-1),_=e("p",null,[t("連絡先 "),e("a",{href:"mailto:tomoyukimano@gmail.com",target:"_blank",rel:"noreferrer"},"tomoyukimano@gmail.com")],-1),p=e("p",null,[t("GitHub "),e("a",{href:"https://github.com/tomomano",target:"_blank",rel:"noreferrer"},"https://github.com/tomomano")],-1);function h(u,f,k,g,b,v){const o=a;return n(),s("div",null,[i,m(o,{readTime:"1",words:"110"}),l,d,_,p])}const N=r(c,[["render",h]]);export{w as __pageData,N as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,o as n,c as s,H as m,k as e,a as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"著者紹介","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/author.md","filePath":"development/aws/author.md","lastUpdated":1699051935000}'),c={name:"development/aws/author.md"},i=e("h1",{id:"著者紹介",tabindex:"-1"},[t("著者紹介 "),e("a",{class:"header-anchor",href:"#著者紹介","aria-label":'Permalink to "著者紹介"'},"​")],-1),l=e("p",null,"真野 智之 (Tomoyuki Mano)",-1),d=e("p",null,"情報理工学博士 (東京大学大学院情報理工学系研究科システム情報学専攻). 2021 年より日本学術振興会特別研究員 (PD) (現職). 沖縄科学技術大学院大学 (OIST) にてポスドク研究員として働く. 現在の研究分野は神経科学・神経情報学. 趣味は料理・ランニング・鉄道・アニメ,村上春樹の熱烈な愛読家.",-1),_=e("p",null,[t("連絡先 "),e("a",{href:"mailto:tomoyukimano@gmail.com",target:"_blank",rel:"noreferrer"},"tomoyukimano@gmail.com")],-1),p=e("p",null,[t("GitHub "),e("a",{href:"https://github.com/tomomano",target:"_blank",rel:"noreferrer"},"https://github.com/tomomano")],-1);function h(u,f,k,g,b,v){const o=a;return n(),s("div",null,[i,m(o,{readTime:"1",words:"110"}),l,d,_,p])}const N=r(c,[["render",h]]);export{w as __pageData,N as default}; diff --git a/assets/development_aws_aws-batch.md.76d54c51.js b/assets/development_aws_aws-batch.md.76d54c51.js new file mode 100644 index 00000000..190dcec9 --- /dev/null +++ b/assets/development_aws_aws-batch.md.76d54c51.js @@ -0,0 +1,456 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as c,e as t,f as r,g as y,h as i,i as A,j as u,k as C,l as b,m as D,n as d,o as m,p as F,q as B,r as E,s as h}from"./chunks/cloud_development.e43e5d4a.js";import{_,o as g,c as q,H as f,k as s,a as v,Q as k}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const X=JSON.parse('{"title":"Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/aws-batch.md","filePath":"development/aws/aws-batch.md","lastUpdated":1699051935000}'),S={name:"development/aws/aws-batch.md"},j=s("h1",{id:"hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する",tabindex:"-1"},[v("Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する "),s("a",{class:"header-anchor",href:"#hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する","aria-label":'Permalink to "Hands-on \\#4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する"'},"​")],-1),x=k('

    ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

    本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

    Auto scaling groups (ASG)

    ハンズオンに入っていく前に, Auto scaling groups (ASG) とよばれる EC2 の概念を知っておく必要がある.

    ECS の概要を示した (#ecs_overview) を振り返って見てほしい. 前章 ( (#sec_fargate_qabot)) でも説明したが, ECS のクラスターで計算を担う実体としては EC2 と Fargate を指定することができる. Fargate については前章で記述した. Fargate を用いると,自在にスケールする計算環境をとても簡単な設定で構築することができた. しかし, GPU を利用することができないなど,いくつかの制約があった. EC2 を使用した計算環境を指定することで,プログラミングの複雑度は増すが, GPU やその他のより高度かつ複雑な設定を伴ったクラスターを構築することができる.

    EC2 クラスターには ASG と呼ばれるサービスが配置される. ASG は複数の EC2 インスタンスをロジカルな単位でグループ化することでクラスターを構成する. ASG はクラスター内に新しいインスタンスを起動する,あるいは不要になったインスタンスを停止するなどのスケーリングを担う. ASG で重要な概念として, desired capacity, minimum capacity, maximum capacity というパラメータがある. minimum capacity, maximum capacity は,それぞれクラスター内に配置できるインスタンスの数の最小値・最大値を指定するパラメータである. 前者は,クラスターに負荷がかかっていない場合でもアイドリング状態にあるインスタンスを維持することで,急に負荷が増大した時などのバッファーとして作用することができる. 後者は,負荷が急に増えたときに,過剰な数のインスタンスが起動する事態を防ぎ,経済的なコストの上限を定める役割を果たす.

    desired capacity が,その時々でシステムが要求するインスタンスの数を指定する. desired capacity は,例えば 24 時間のリズムに合わせてインスタンスの数を増減させる (昼は多く夜は少なくなど) などの決まったスケジュールに基づいた設定を適用することができる. あるいはクラスター全体にかかっている負荷に応じて, desired capacity を動的に制御することも可能である. どのような基準でクラスターのスケーリングを行うかを定めるルールのことを,スケーリングポリシーとよぶ. たとえば,クラスター全体の稼働率 (負荷) を常に 80% に維持する,などのスケーリングポリシーが想定できる. この場合,クラスター全体の負荷が 80%を下回ったときにはクラスターからインスタンスが削除され,80%を超える (あるいは超えると予測される) 場合はインスタンスを追加する,という操作が ASG によって自動的に行われる.

    上記のようなパラメータを検討し,ユーザーは ASG を作成する. ASG を作成したのち, ECS との連携をプログラムしてあげることで, ECS を介して ASG による EC2 クラスターにタスクを投入することが可能になる.

    AWS Batch

    AWS Batch のアイコン

    先に説明したように, ECS と ASG を組み合わせることで,所望の計算クラスターを構築することが可能である. しかしながら, ECS と ASG にはかなり込み入った設定が必要であり,初心者にとっても経験者にとってもなかなか面倒なプログラミングが要求される. そこで, ECS と ASG によるクラスターの設計を自動化してくれるサービスが提供されている. それが AWS Batch である.

    AWS Batch はその名のとおりバッチ (Batch) 化されたジョブ (入力データだけが異なる独立した演算が繰り返し実行されること) を想定している. 多くの科学計算や機械学習がバッチ計算に当てはまる. たとえば,初期値のパラメータを変えて複数のシミュレーションを走らせる,といったケースだ. AWS Batch を用いることの利点は,クラスターのスケーリングやジョブの割り振りはすべて自動で実行され, ユーザーはクラウドの舞台裏の詳細を気にすることなく,大量のジョブを投入できるシステムが手に入る点である. が,知識として背後では ECS/ASG/EC2 の三つ巴が協調して動作しているという点は知っておいてほしい.

    AWS Batch では,ジョブの投入・管理をスムーズに行うため,次のような概念が定義されている (figure_title). まず, ジョブ (Job) というのが,AWS Batch によって実行される一つの計算の単位である. Job definitions とはジョブの内容を定義するものであり,これには実行されるべき Docker のイメージのアドレスや,割り当てる CPU・RAM の容量,環境変数などの設定が含まれる. Job definition に基づいて個々のジョブが実行される. ジョブが実行されると,ジョブは Job queues に入る. Job queues とは,実行待ち状態にあるジョブの列のことであり,時間的に最も先頭に投入されたジョブが最初に実行される. また,複数の queue を配置し, queue ごとに priority (優先度) を設定することが可能であり, priority の高い queue に溜まったジョブが優先的に実行される (筆者はこれをディズニーランドの"ファストパス"を連想して捉えている). Compute environment とは,先述したクラスターとほぼ同義の概念であり,計算が実行される場所 (EC2 や Fargate からなるクラスター) を指す. Compute environment には,使用する EC2 のインスタンスタイプや同時に起動するインスタンス数の上限などの簡易なスケーリングポリシーが指定されている. Job queues は Compute environment の空き状況を監視しており, それに応じてジョブを Compute environment に投下する.

    以上が AWS Batch を使用するうえで理解しておかなければならない概念であるが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは,実際に自分で手を動かしながら学んでいこう.

    AWS Batch の主要な概念

    EC2 or Fargate?

    ECS でクラスターを構成する際,計算を実行する場として EC2 と Fargate の二つの選択肢があることを説明した. それぞれ長所と短所を抱えているのだが,どのような場合にどちらを使うべきだろうか? それを検討するため,まずは table_title を見てみよう. これは EC2 と Fargate の特徴をまとめたものである. 説明の都合上,大幅な粗視化が行われている点は留意していただきたい.

    EC2 vs Fargate
    EC2Fargate

    Compute capacity

    Medium to large

    Small to medium

    GPU

    Yes

    No

    Launch speed

    Slow

    Fast

    Task placement flexibility

    Low

    High

    Programming complexity

    High

    Low

    これまでに見てきたように, EC2 は最大の CPU 数・メモリーサイズが大きかったり, GPU を利用できたりするなど,単一のインスタンスでの計算能力は高い. 対して, Fargate は単一インスタンスの最大 CPU 数は 4 コアが上限である. その一方で,インスタンスの起動に要する時間は Fargate のほうが圧倒的に早く,より俊敏にクラスターのスケーリングを行うことができる. また,タスクをクラスターに投入する際のフレキシビリティも Fargate のほうが高い. フレキシビリティというのは,例えば一つのインスタンスで 2 つ以上のコンテナを走らせる,などの状況である. 単位 CPU あたりで処理されるタスクの数を最大化する際には,このような設計がしばしば採用される. プログラミングの複雑さという観点からは, Fargate のほうが一般的にシンプルな実装になる.

    このように, EC2 と Fargate は互いに相補的な特性を有しており,アプリケーションによって最適な計算環境は検討される必要がある. また,EC2 と Fargate を両方用いたハイブリッドクラスターというのも定義可能であり,そのような選択肢もしばしば用いられる.

    準備

    ハンズオンのソースコードは GitHub の handson/aws-batch にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,アメリカ東部 (us-east-1) リージョンでは 0.526 $/hour のコストが発生する. 東京 (ap-northeast-1) を選択した場合は 0.71 $/hour のコストが発生する.

    (#sec:jupyter_and_deep_learning_setup) でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, (#sec_mnist_using_jupyter) で扱った MNIST 手書き文字認識の問題を再度取り上げよう. (#sec_mnist_using_jupyter) では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    ランダムサーチ法とは,ハイパーパラメータの組をある範囲の中でランダムに抽出し,大量に試行されたランダムな組の中から最適なパラメータの組を見出す方法である. すべての可能性を網羅的に探索できるわけではないが,調整すべきパラメータの数が多数ある場合に,グリッドサーチよりも効率的に広い探索空間をカバーすることができる.

    ベイズ最適化を用いた方法では,過去の探索結果から次にどの組み合わせを探索すべきかという指標を計算し,次に探索するパラメータを決定する. これにより,理論的にはグリッドサーチやランダムサーチ法よりも少ない試行回数で最適なパラメータにたどり着くことができる.

    並列化の観点でいうと,グリッドサーチとランダムサーチは各ハイパーパラメータの組の計算は独立に実行することができるため並列化が容易である. このように独立したジョブとして分割・並列化可能な問題を Embarrassingly parallel な問題とよぶ (直訳すると"恥ずかしいほど並列化可能な問題",ということになる). Embarrassingly parallel な問題はクラウドの強力な計算リソースを用いることで,非常なシンプルな実装で解くことができる. この章ではこのようなタイプの並列計算を取り上げる.

    一方,ベイズ最適化による方法は,過去の結果をもとに次の探索が決定されるので,並列化はそれほど単純ではない. 最近では optuna などのハイパーパラメータ探索のためのライブラリが発達しており,ベイズ最適化の数理的な処理を自動で実行してくれるので便利である. これらのライブラリを使うと,もし一台のコンピュータ (ノード) の中に複数の GPU が存在する場合は,並列に計算を実行することができる. しかしながら,一台のノードにとどまらず,複数のノードをまたいだ並列化は,高度なプログラミングテクニックが必要とされるだけでなく,ノード間の接続様式などクラウドのアーキテクチャにも深く依存するものである. 本書ではここまで高度なクラウドの使用方法には立ち入らない.

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に (#sec_mnist_using_jupyter) のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    sh
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. (#sec_jupyter_and_deep_learning) のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    +

    このコマンドでは,--gpus all というパラメータが加わった.

    CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

    (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

    これはオーバーフィッティングとよばれる現象で,ニューラルネットが訓練データに過度に最適化され,訓練データの外のデータに対しての精度 (汎化性能) が向上していないことを示している. このような場合の対処法として, Early stopping とよばれるテクニックが知られている. Early stopping とは,検証データの Loss を追跡し,それが減少から増加に転じるエポックで学習をうち止め,そのエポックでのウェイトパラメータを採用する,というものである. 本ハンズオンでも, Early stopping によって訓練の終了を判断し,モデルの性能評価を行っていく.

    MNIST 手書き文字データセットでは,訓練データとして 60,000 枚,テストデータとして 10,000 枚の画像が与えられている. 本ハンズオンで使用するコードでは,訓練データのうち 80% の 48,000 枚を訓練データとして使用し,残り 20% の 12,000 枚を検証データとして用いている. 詳しくはソースコードを参照のこと.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントは,あるハイパーパラメータの組を指定して Batch にジョブを提出する

    • Batch はジョブを受け取ると, EC2 からなるクラスターで計算を実行する

    • クラスター内では g4dn.xlarge インスタンスが起動する

    • Docker イメージは, AWS 内に用意された ECR (Elastic Container Registry) から取得される

    • 複数のジョブが投下された場合は,その数だけのインスタンスが起動し並列に実行される

    • 各ジョブによる計算の結果は S3 に保存される

    • 最後にクライアントは S3 から結果をダウンロードし,最適なハイパーパラメータの組を決定する

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    python
    class SimpleBatch(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    +
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
    +
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
    +
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
    +
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
    +
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
    +
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    class SimpleBatch(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    +
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
    +
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
    +
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
    +
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
    +
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
    +
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    • で,計算結果を保存するための S3 バケットを用意している

    • で, Compute environment を定義している. ここでは g4dn.xlarge のインスタンスタイプを使用するとし,最大の vCPU 使用数は 64 と指定している. また,最小の vCPU は 0 である. 今回は,負荷がかかっていないときにアイドリング状態にあるインスタンスを用意する利点は全くないので,ここは 0 にするのが望ましい.

    • で, <2> で作成した Compute environment と紐付いた Job queue を定義している.

    • で,ジョブが計算結果を S3 に書き込むことができるよう, IAM ロールを定義している. (IAM とはリソースがもつ権限を管理する仕組みである.詳しくは (#sec:bashoutter_iam) を参照)

    • では, Docker image を配置するための ECR を定義している.

    • で Job definition を作成している. ここでは,4 vCPU, 12000 MB (=12GB) の RAM を使用するように指定している. また,今後必要となる環境変数 (BUCKET_NAME) を設定している. さらに, <4> で作った IAM を付与している.

    g4dn.xlarge は 1 台あたり 4 vCPU が割り当てられている. このプログラムでは Compute environment の maximum vCPUs を 64 と指定しているので,最大で 16 台のインスタンスが同時に起動することになる. ここで maxium vCPUs を 64 に限定しているのは,なんらかのミスで意図せぬジョブを大量にクラスターに投入してしまった事態で,高額の AWS 利用料金が発生するのを防ぐためである. もし,自分のアプリケーションで必要と判断したならば自己責任において 64 よりも大きな数を設定して構わない.

    ここで注意が一点ある. AWS では各アカウントごとに EC2 で起動できるインスタンスの上限が設定されている. この上限は AWS コンソールにログインし, EC2 コンソールの左側メニューバーの Limits をクリックすることで確認できる (figure_title). g4dn.xlarge (EC2 の区分でいうと G ファミリーに属する) の制限を確認するには, Running On-Demand All G instances という名前の項目を見る. ここにある数字が, AWS によって課されたアカウントの上限であり,この上限を超えたインスタンスを起動することはできない. もし,自分の用途に対して上限が低すぎる場合は,上限の緩和申請を行うことができる. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    EC2コンソールから各種の上限を確認する

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    次に,Job queue overview にある SimpleBatch-queue という項目に注目してほしい. ここでは実行待ちのジョブ・実行中のジョブ・実行が完了したジョブを一覧で確認することができる. PENDING, RUNNING, SUCCEEDED, FAILED などのカラムがあることが確認できる.ジョブが進行するにつれて,ジョブの状態がこのカラムにしたがって遷移していく. 後でジョブを実際にサブミットしたときに戻ってこよう.

    最後に,今回作成した Job definition を確認しよう. 左側のメニューから Job definitions を選択し,次の画面で SimpleBatchjob-definition という項目を見つけて開く. ここから Job definition の詳細を閲覧することができる (figure_title). 中でも重要な情報としては, vCPUs, Memory, GPU がそれぞれ Docker に割り当てられる vCPU・メモリー・ GPU の量を規定している. また, Image と書いてあるところに,ジョブで使用される Docker イメージが指定されている. ここでは, ECR のレポジトリを参照している. 現時点ではこの ECR は空である. 次のステップとして,この ECR にイメージを配置する作業を行おう.

    AWS Batch から Job definition を確認

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン ( (#sec_fargate_qabot)) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    python
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
    +
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
    +
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    • で,新規の ECR を作成している.

    • で Job definition を定義する中で,イメージを <1> で作った ECR から取得するように指定している. これと同時に, Job definition には ECR へのアクセス権限が IAM を通じて自動的に付与される.

    さて,スタックをデプロイした時点では, ECR は空っぽである. ここに自分のアプリケーションで使う Docker イメージを push してあげる必要がある.

    そのために,まずは AWS コンソールから ECR の画面を開こう (検索バーに Elastic Container Registry と入力すると出てくる). Private というタブを選択すると, simplebatch-repositoryXXXXXX という名前のレポジトリが見つかるだろう (figure_title).

    ECR のコンソール画面

    次に,このレポジトリの名前をクリックするとレポジトリの詳細画面に遷移する. そうしたら,画面右上にある View push commands というボタンをクリックする. すると figure_title のようなポップアップ画面が立ち上がる.

    ECR への push コマンド

    このポップアップ画面で表示されている四つのコマンドを順番に実行していくことで,手元の Docker イメージを ECR に push することができる. push を実行する前に, AWS の認証情報が設定されていることを確認しよう. そのうえで,ハンズオンのソースコードの中にある docker/ という名前のディレクトリに移動する. そうしたら,ポップアップ画面で表示されたコマンドを上から順に実行していく.

    ポップアップで表示されるコマンドの 2 つめを見てみると docker build -t XXXXX . となっている. 最後の . が重要で,これは 現在のディレクトリにある Dockerfile を使ってイメージをビルドせよ という意味である. このような理由で, Dockerfile が置いてあるディレクトリに移動する必要がある.

    四つ目のコマンドは,数 GB あるイメージを ECR にアップロードするので少し時間がかかるかもしれないが,これが完了するとめでたくイメージが ECR に配置されたことになる. もう一度 ECR のコンソールを見てみると,確かにイメージが配置されていることが確認できる (figure_title). これで,AWS Batch を使ってジョブを実行させるための最後の準備が完了した.

    ECR へ image の配置が完了した

    単一のジョブを実行する

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    sh
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    python
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
    +
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
    +
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    python
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    python
    # [4]
    +submit_job(0.01, 0.1, 100)
    # [4]
    +submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは (#aws_cli_install)), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    AWS Batch でジョブが実行されている様子

    figure_title で赤で囲った箇所に注目してほしい. 一つのジョブが投入されると,それは SUBMITTED という状態を経て RUNNABLE という状態に遷移する. RUNNABLE とは, ジョブを実行するためのインスタンスが Compute environment に不足しているため,新たなインスタンスが起動されるのを待っている状態に相当する. インスタンスの準備が整うと,ジョブの状態は STARTING を経て RUNNING に至る.

    次に,ジョブのステータスが RUNNING のときの Compute environment の Desired vCPU を見てみよう (figure_title で紫で囲った箇所). ここで 4 と表示されているのは, g4dn.xlarge インスタンス一つ分の vCPU の数である. ジョブの投入に応じて,それを実行するのに最低限必要な EC2 インスタンスが起動されたことが確認できる (興味のある人は, EC2 コンソールも同時に覗いてみるとよい).

    しばらく経つと,ジョブの状態は RUNNING から SUCCEEDED (あるいは何らかの理由でエラーが発生したときには FAILED) に遷移する. 今回のハンズオンで使っている MNIST の学習はだいたい 10 分くらいで完了するはずである. ジョブの状態が SUCCEEDED になるまで見届けよう.

    ジョブが完了すると,学習の結果 (エポックごとの Loss と Accuracy を記録した CSV ファイル) は S3 に保存される. AWS コンソールからこれを確認しよう.

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    python
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    python
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
    +
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
    +
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
    +
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
    +
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
    +
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
    +
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    python
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    python
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    複数のジョブを同時投入したときの Job 一覧

    今度は EC2 コンソールを見てみよう. 左のメニューから Instances を選択すると, figure_title に示すような起動中のインスタンスの一覧が表示される. g4dn.xlarge が 9 台稼働しているのが確認できる. Batch がジョブの投下に合わせて必要な数のインスタンスを起動してくれたのだ!

    複数のジョブを同時投入したときの EC2 インスタンスの一覧

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    python
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
    +
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
    +
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
    +
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
    +
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    今回のパラメータサーチは勉強用に極めて単純化されたものである点は承知いただきたい.

    たとえば,今回は学習率が 0.1 が最も良いとされたが,それは訓練のエポックを 100 に限定しているからかもしれない. 学習率が低いとその分訓練に必要なエポック数も多くなる. 訓練のエポック数をもっと増やせばまた違った結果が観察される可能性はある.

    また,今回は MNIST の訓練データ 60,000 枚のうち, 48,000 枚を訓練データ,残り 12,000 枚を検証データとして用いた. この分割は乱数を固定してランダムに行ったが,もしこの分割によるデータのバイアスを気にするならば, k 個の異なる学習・検証データの分割をあらかじめ用意して,複数回モデルの評価を行う (k-fold cross-validation) 方法も,より精緻なアプローチとして考えられる.

    以上のようにして, CNN を用いた MNIST 分類モデルのハイパーパラメータの最適化の一連の流れを体験した. AWS Batch を利用することで,比較的少ないプログラミングで,動的に EC2 クラスターを制御し,並列にジョブを処理するシステムが構築できた. ここまで EC2 を使いこなすことができれば,多くの問題を自力で解くことが可能になるだろう!

    スタックの削除

    これにて,本ハンズオンは終了である.最後にスタックを削除しよう. 今回のスタックを削除するにあたり,ECR に配置された Docker のイメージは手動で削除されなければならない (これをしないと, cdk destroy を実行したときにエラーになってしまう. これは CloudFormation の仕様なので従うしかない).

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, (#sec_jupyter_and_deep_learning) で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを (#sec_fargate_qabot) を参考に構築する.

    実際,本書ではこの流れに沿って演習を進めてきた. MNIST タスクを解くモデルを,最初 Jupyter Notebook を使用して実験し,そのコードをほとんどそのまま Docker にパッケージし, AWS Batch を用いてハイパーパラメータサーチを行った. このサイクルを繰り返すことで,クラウドを最大限に活用した機械学習アプリケーションの開発を進めることができる.

    クラウドを活用した機械学習アプリケーションの開発フロー

    小括

    ここまでが,本書第二部の内容である. 第一部に引き続き盛りだくさんの内容であったが,ついてこれたであろうか?

    第二部ではまず最初に,深層学習の計算をクラウドで実行するため, GPU 搭載型の EC2 インスタンスの起動について解説した. さらに,ハンズオンでは,クラウドに起動した仮想サーバーを使って MNIST 文字認識タスクを解くニューラルネットを訓練した ( (#sec_jupyter_and_deep_learning)).

    また,より大規模な機械学習アプリケーションを作るための手段として, Docker と ECS によるクラスターの初歩を説明した ( (#sec_docker_introduction)). その応用として,英語で与えられた文章問題への回答を自動で生成するボットをクラウドに展開した ( (#sec_fargate_qabot)). タスクの投入に応じて動的に計算リソースが作成・削除される様子を実際に体験できただろう.

    さらに, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する では AWS Batch を用いてニューラルネットの学習を並列に実行する方法を紹介した. ここで紹介した方法は,ミニマムであるが,計算機システムを大規模化していくためのエッセンスが網羅されている. これらのハンズオン体験から,クラウド技術を応用してどのように現実世界の問題を解いていくのか,なんとなくイメージが伝わっただろうか?

    本書の第三部では,さらにレベルアップし,サーバーレスアーキテクチャという最新のクラウドの設計手法について解説する. その応用として,ハンズオンでは簡単な SNS サービスをゼロから実装する. 引き続きクラウドの最先端の世界を楽しんでいこう!

    ',162);function w(N,R,P,T,U,W){const n=a;return g(),q("div",null,[j,f(n,{readTime:"20",words:"5k"}),x])}const M=_(S,[["render",w]]);export{X as __pageData,M as default}; diff --git a/assets/development_aws_aws-batch.md.76d54c51.lean.js b/assets/development_aws_aws-batch.md.76d54c51.lean.js new file mode 100644 index 00000000..b48425a3 --- /dev/null +++ b/assets/development_aws_aws-batch.md.76d54c51.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as c,e as t,f as r,g as y,h as i,i as A,j as u,k as C,l as b,m as D,n as d,o as m,p as F,q as B,r as E,s as h}from"./chunks/cloud_development.e43e5d4a.js";import{_,o as g,c as q,H as f,k as s,a as v,Q as k}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const X=JSON.parse('{"title":"Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/aws-batch.md","filePath":"development/aws/aws-batch.md","lastUpdated":1699051935000}'),S={name:"development/aws/aws-batch.md"},j=s("h1",{id:"hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する",tabindex:"-1"},[v("Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する "),s("a",{class:"header-anchor",href:"#hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する","aria-label":'Permalink to "Hands-on \\#4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する"'},"​")],-1),x=k("",162);function w(N,R,P,T,U,W){const n=a;return g(),q("div",null,[j,f(n,{readTime:"20",words:"5k"}),x])}const M=_(S,[["render",w]]);export{X as __pageData,M as default}; diff --git a/assets/development_aws_aws-batch.md.de2d649a.js b/assets/development_aws_aws-batch.md.de2d649a.js deleted file mode 100644 index 60c2d9bb..00000000 --- a/assets/development_aws_aws-batch.md.de2d649a.js +++ /dev/null @@ -1,456 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as o,c as e,d as t,e as c,f as r,g as y,h as i,i as u,j as b,k as d,l as m,m as B,n as A,o as h,p as _,q as g,r as f,s as q}from"./chunks/cloud_development.e43e5d4a.js";import{_ as v,o as k,c as D,H as C,k as s,a as E,Q as S}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const X=JSON.parse('{"title":"Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/aws-batch.md","filePath":"development/aws/aws-batch.md","lastUpdated":1695377563000}'),j={name:"development/aws/aws-batch.md"},w=s("h1",{id:"hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する",tabindex:"-1"},[E("Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する "),s("a",{class:"header-anchor",href:"#hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する","aria-label":'Permalink to "Hands-on \\#4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する"'},"​")],-1),x=S('

    ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

    本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

    Auto scaling groups (ASG)

    ハンズオンに入っていく前に, Auto scaling groups (ASG) とよばれる EC2 の概念を知っておく必要がある.

    ECS の概要を示した (#ecs_overview) を振り返って見てほしい. 前章 ( (#sec_fargate_qabot)) でも説明したが, ECS のクラスターで計算を担う実体としては EC2 と Fargate を指定することができる. Fargate については前章で記述した. Fargate を用いると,自在にスケールする計算環境をとても簡単な設定で構築することができた. しかし, GPU を利用することができないなど,いくつかの制約があった. EC2 を使用した計算環境を指定することで,プログラミングの複雑度は増すが, GPU やその他のより高度かつ複雑な設定を伴ったクラスターを構築することができる.

    EC2 クラスターには ASG と呼ばれるサービスが配置される. ASG は複数の EC2 インスタンスをロジカルな単位でグループ化することでクラスターを構成する. ASG はクラスター内に新しいインスタンスを起動する,あるいは不要になったインスタンスを停止するなどのスケーリングを担う. ASG で重要な概念として, desired capacity, minimum capacity, maximum capacity というパラメータがある. minimum capacity, maximum capacity は,それぞれクラスター内に配置できるインスタンスの数の最小値・最大値を指定するパラメータである. 前者は,クラスターに負荷がかかっていない場合でもアイドリング状態にあるインスタンスを維持することで,急に負荷が増大した時などのバッファーとして作用することができる. 後者は,負荷が急に増えたときに,過剰な数のインスタンスが起動する事態を防ぎ,経済的なコストの上限を定める役割を果たす.

    desired capacity が,その時々でシステムが要求するインスタンスの数を指定する. desired capacity は,例えば 24 時間のリズムに合わせてインスタンスの数を増減させる (昼は多く夜は少なくなど) などの決まったスケジュールに基づいた設定を適用することができる. あるいはクラスター全体にかかっている負荷に応じて, desired capacity を動的に制御することも可能である. どのような基準でクラスターのスケーリングを行うかを定めるルールのことを,スケーリングポリシーとよぶ. たとえば,クラスター全体の稼働率 (負荷) を常に 80% に維持する,などのスケーリングポリシーが想定できる. この場合,クラスター全体の負荷が 80%を下回ったときにはクラスターからインスタンスが削除され,80%を超える (あるいは超えると予測される) 場合はインスタンスを追加する,という操作が ASG によって自動的に行われる.

    上記のようなパラメータを検討し,ユーザーは ASG を作成する. ASG を作成したのち, ECS との連携をプログラムしてあげることで, ECS を介して ASG による EC2 クラスターにタスクを投入することが可能になる.

    AWS Batch

    AWS Batch のアイコン

    先に説明したように, ECS と ASG を組み合わせることで,所望の計算クラスターを構築することが可能である. しかしながら, ECS と ASG にはかなり込み入った設定が必要であり,初心者にとっても経験者にとってもなかなか面倒なプログラミングが要求される. そこで, ECS と ASG によるクラスターの設計を自動化してくれるサービスが提供されている. それが AWS Batch である.

    AWS Batch はその名のとおりバッチ (Batch) 化されたジョブ (入力データだけが異なる独立した演算が繰り返し実行されること) を想定している. 多くの科学計算や機械学習がバッチ計算に当てはまる. たとえば,初期値のパラメータを変えて複数のシミュレーションを走らせる,といったケースだ. AWS Batch を用いることの利点は,クラスターのスケーリングやジョブの割り振りはすべて自動で実行され, ユーザーはクラウドの舞台裏の詳細を気にすることなく,大量のジョブを投入できるシステムが手に入る点である. が,知識として背後では ECS/ASG/EC2 の三つ巴が協調して動作しているという点は知っておいてほしい.

    AWS Batch では,ジョブの投入・管理をスムーズに行うため,次のような概念が定義されている (figure_title). まず, ジョブ (Job) というのが,AWS Batch によって実行される一つの計算の単位である. Job definitions とはジョブの内容を定義するものであり,これには実行されるべき Docker のイメージのアドレスや,割り当てる CPU・RAM の容量,環境変数などの設定が含まれる. Job definition に基づいて個々のジョブが実行される. ジョブが実行されると,ジョブは Job queues に入る. Job queues とは,実行待ち状態にあるジョブの列のことであり,時間的に最も先頭に投入されたジョブが最初に実行される. また,複数の queue を配置し, queue ごとに priority (優先度) を設定することが可能であり, priority の高い queue に溜まったジョブが優先的に実行される (筆者はこれをディズニーランドの"ファストパス"を連想して捉えている). Compute environment とは,先述したクラスターとほぼ同義の概念であり,計算が実行される場所 (EC2 や Fargate からなるクラスター) を指す. Compute environment には,使用する EC2 のインスタンスタイプや同時に起動するインスタンス数の上限などの簡易なスケーリングポリシーが指定されている. Job queues は Compute environment の空き状況を監視しており, それに応じてジョブを Compute environment に投下する.

    以上が AWS Batch を使用するうえで理解しておかなければならない概念であるが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは,実際に自分で手を動かしながら学んでいこう.

    AWS Batch の主要な概念

    EC2 or Fargate?

    ECS でクラスターを構成する際,計算を実行する場として EC2 と Fargate の二つの選択肢があることを説明した. それぞれ長所と短所を抱えているのだが,どのような場合にどちらを使うべきだろうか? それを検討するため,まずは table_title を見てみよう. これは EC2 と Fargate の特徴をまとめたものである. 説明の都合上,大幅な粗視化が行われている点は留意していただきたい.

    EC2 vs Fargate
    EC2Fargate

    Compute capacity

    Medium to large

    Small to medium

    GPU

    Yes

    No

    Launch speed

    Slow

    Fast

    Task placement flexibility

    Low

    High

    Programming complexity

    High

    Low

    これまでに見てきたように, EC2 は最大の CPU 数・メモリーサイズが大きかったり, GPU を利用できたりするなど,単一のインスタンスでの計算能力は高い. 対して, Fargate は単一インスタンスの最大 CPU 数は 4 コアが上限である. その一方で,インスタンスの起動に要する時間は Fargate のほうが圧倒的に早く,より俊敏にクラスターのスケーリングを行うことができる. また,タスクをクラスターに投入する際のフレキシビリティも Fargate のほうが高い. フレキシビリティというのは,例えば一つのインスタンスで 2 つ以上のコンテナを走らせる,などの状況である. 単位 CPU あたりで処理されるタスクの数を最大化する際には,このような設計がしばしば採用される. プログラミングの複雑さという観点からは, Fargate のほうが一般的にシンプルな実装になる.

    このように, EC2 と Fargate は互いに相補的な特性を有しており,アプリケーションによって最適な計算環境は検討される必要がある. また,EC2 と Fargate を両方用いたハイブリッドクラスターというのも定義可能であり,そのような選択肢もしばしば用いられる.

    準備

    ハンズオンのソースコードは GitHub の handson/aws-batch にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,アメリカ東部 (us-east-1) リージョンでは 0.526 $/hour のコストが発生する. 東京 (ap-northeast-1) を選択した場合は 0.71 $/hour のコストが発生する.

    (#sec:jupyter_and_deep_learning_setup) でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, (#sec_mnist_using_jupyter) で扱った MNIST 手書き文字認識の問題を再度取り上げよう. (#sec_mnist_using_jupyter) では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    ランダムサーチ法とは,ハイパーパラメータの組をある範囲の中でランダムに抽出し,大量に試行されたランダムな組の中から最適なパラメータの組を見出す方法である. すべての可能性を網羅的に探索できるわけではないが,調整すべきパラメータの数が多数ある場合に,グリッドサーチよりも効率的に広い探索空間をカバーすることができる.

    ベイズ最適化を用いた方法では,過去の探索結果から次にどの組み合わせを探索すべきかという指標を計算し,次に探索するパラメータを決定する. これにより,理論的にはグリッドサーチやランダムサーチ法よりも少ない試行回数で最適なパラメータにたどり着くことができる.

    並列化の観点でいうと,グリッドサーチとランダムサーチは各ハイパーパラメータの組の計算は独立に実行することができるため並列化が容易である. このように独立したジョブとして分割・並列化可能な問題を Embarrassingly parallel な問題とよぶ (直訳すると"恥ずかしいほど並列化可能な問題",ということになる). Embarrassingly parallel な問題はクラウドの強力な計算リソースを用いることで,非常なシンプルな実装で解くことができる. この章ではこのようなタイプの並列計算を取り上げる.

    一方,ベイズ最適化による方法は,過去の結果をもとに次の探索が決定されるので,並列化はそれほど単純ではない. 最近では optuna などのハイパーパラメータ探索のためのライブラリが発達しており,ベイズ最適化の数理的な処理を自動で実行してくれるので便利である. これらのライブラリを使うと,もし一台のコンピュータ (ノード) の中に複数の GPU が存在する場合は,並列に計算を実行することができる. しかしながら,一台のノードにとどまらず,複数のノードをまたいだ並列化は,高度なプログラミングテクニックが必要とされるだけでなく,ノード間の接続様式などクラウドのアーキテクチャにも深く依存するものである. 本書ではここまで高度なクラウドの使用方法には立ち入らない.

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に (#sec_mnist_using_jupyter) のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    sh
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. (#sec_jupyter_and_deep_learning) のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    -

    このコマンドでは,--gpus all というパラメータが加わった.

    CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

    (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

    これはオーバーフィッティングとよばれる現象で,ニューラルネットが訓練データに過度に最適化され,訓練データの外のデータに対しての精度 (汎化性能) が向上していないことを示している. このような場合の対処法として, Early stopping とよばれるテクニックが知られている. Early stopping とは,検証データの Loss を追跡し,それが減少から増加に転じるエポックで学習をうち止め,そのエポックでのウェイトパラメータを採用する,というものである. 本ハンズオンでも, Early stopping によって訓練の終了を判断し,モデルの性能評価を行っていく.

    MNIST 手書き文字データセットでは,訓練データとして 60,000 枚,テストデータとして 10,000 枚の画像が与えられている. 本ハンズオンで使用するコードでは,訓練データのうち 80% の 48,000 枚を訓練データとして使用し,残り 20% の 12,000 枚を検証データとして用いている. 詳しくはソースコードを参照のこと.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントは,あるハイパーパラメータの組を指定して Batch にジョブを提出する

    • Batch はジョブを受け取ると, EC2 からなるクラスターで計算を実行する

    • クラスター内では g4dn.xlarge インスタンスが起動する

    • Docker イメージは, AWS 内に用意された ECR (Elastic Container Registry) から取得される

    • 複数のジョブが投下された場合は,その数だけのインスタンスが起動し並列に実行される

    • 各ジョブによる計算の結果は S3 に保存される

    • 最後にクライアントは S3 から結果をダウンロードし,最適なハイパーパラメータの組を決定する

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    python
    class SimpleBatch(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    -
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    -
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    -
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    -
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    -
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    -
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    class SimpleBatch(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    -
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    -
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    -
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    -
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    -
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    -
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    • で,計算結果を保存するための S3 バケットを用意している

    • で, Compute environment を定義している. ここでは g4dn.xlarge のインスタンスタイプを使用するとし,最大の vCPU 使用数は 64 と指定している. また,最小の vCPU は 0 である. 今回は,負荷がかかっていないときにアイドリング状態にあるインスタンスを用意する利点は全くないので,ここは 0 にするのが望ましい.

    • で, <2> で作成した Compute environment と紐付いた Job queue を定義している.

    • で,ジョブが計算結果を S3 に書き込むことができるよう, IAM ロールを定義している. (IAM とはリソースがもつ権限を管理する仕組みである.詳しくは (#sec:bashoutter_iam) を参照)

    • では, Docker image を配置するための ECR を定義している.

    • で Job definition を作成している. ここでは,4 vCPU, 12000 MB (=12GB) の RAM を使用するように指定している. また,今後必要となる環境変数 (BUCKET_NAME) を設定している. さらに, <4> で作った IAM を付与している.

    g4dn.xlarge は 1 台あたり 4 vCPU が割り当てられている. このプログラムでは Compute environment の maximum vCPUs を 64 と指定しているので,最大で 16 台のインスタンスが同時に起動することになる. ここで maxium vCPUs を 64 に限定しているのは,なんらかのミスで意図せぬジョブを大量にクラスターに投入してしまった事態で,高額の AWS 利用料金が発生するのを防ぐためである. もし,自分のアプリケーションで必要と判断したならば自己責任において 64 よりも大きな数を設定して構わない.

    ここで注意が一点ある. AWS では各アカウントごとに EC2 で起動できるインスタンスの上限が設定されている. この上限は AWS コンソールにログインし, EC2 コンソールの左側メニューバーの Limits をクリックすることで確認できる (figure_title). g4dn.xlarge (EC2 の区分でいうと G ファミリーに属する) の制限を確認するには, Running On-Demand All G instances という名前の項目を見る. ここにある数字が, AWS によって課されたアカウントの上限であり,この上限を超えたインスタンスを起動することはできない. もし,自分の用途に対して上限が低すぎる場合は,上限の緩和申請を行うことができる. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    EC2コンソールから各種の上限を確認する

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    次に,Job queue overview にある SimpleBatch-queue という項目に注目してほしい. ここでは実行待ちのジョブ・実行中のジョブ・実行が完了したジョブを一覧で確認することができる. PENDING, RUNNING, SUCCEEDED, FAILED などのカラムがあることが確認できる.ジョブが進行するにつれて,ジョブの状態がこのカラムにしたがって遷移していく. 後でジョブを実際にサブミットしたときに戻ってこよう.

    最後に,今回作成した Job definition を確認しよう. 左側のメニューから Job definitions を選択し,次の画面で SimpleBatchjob-definition という項目を見つけて開く. ここから Job definition の詳細を閲覧することができる (figure_title). 中でも重要な情報としては, vCPUs, Memory, GPU がそれぞれ Docker に割り当てられる vCPU・メモリー・ GPU の量を規定している. また, Image と書いてあるところに,ジョブで使用される Docker イメージが指定されている. ここでは, ECR のレポジトリを参照している. 現時点ではこの ECR は空である. 次のステップとして,この ECR にイメージを配置する作業を行おう.

    AWS Batch から Job definition を確認

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン ( (#sec_fargate_qabot)) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    python
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    -
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    -
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    • で,新規の ECR を作成している.

    • で Job definition を定義する中で,イメージを <1> で作った ECR から取得するように指定している. これと同時に, Job definition には ECR へのアクセス権限が IAM を通じて自動的に付与される.

    さて,スタックをデプロイした時点では, ECR は空っぽである. ここに自分のアプリケーションで使う Docker イメージを push してあげる必要がある.

    そのために,まずは AWS コンソールから ECR の画面を開こう (検索バーに Elastic Container Registry と入力すると出てくる). Private というタブを選択すると, simplebatch-repositoryXXXXXX という名前のレポジトリが見つかるだろう (figure_title).

    ECR のコンソール画面

    次に,このレポジトリの名前をクリックするとレポジトリの詳細画面に遷移する. そうしたら,画面右上にある View push commands というボタンをクリックする. すると figure_title のようなポップアップ画面が立ち上がる.

    ECR への push コマンド

    このポップアップ画面で表示されている四つのコマンドを順番に実行していくことで,手元の Docker イメージを ECR に push することができる. push を実行する前に, AWS の認証情報が設定されていることを確認しよう. そのうえで,ハンズオンのソースコードの中にある docker/ という名前のディレクトリに移動する. そうしたら,ポップアップ画面で表示されたコマンドを上から順に実行していく.

    ポップアップで表示されるコマンドの 2 つめを見てみると docker build -t XXXXX . となっている. 最後の . が重要で,これは 現在のディレクトリにある Dockerfile を使ってイメージをビルドせよ という意味である. このような理由で, Dockerfile が置いてあるディレクトリに移動する必要がある.

    四つ目のコマンドは,数 GB あるイメージを ECR にアップロードするので少し時間がかかるかもしれないが,これが完了するとめでたくイメージが ECR に配置されたことになる. もう一度 ECR のコンソールを見てみると,確かにイメージが配置されていることが確認できる (figure_title). これで,AWS Batch を使ってジョブを実行させるための最後の準備が完了した.

    ECR へ image の配置が完了した

    単一のジョブを実行する

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    sh
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    python
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    -
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    -
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    python
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    python
    # [4]
    -submit_job(0.01, 0.1, 100)
    # [4]
    -submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは (#aws_cli_install)), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    AWS Batch でジョブが実行されている様子

    figure_title で赤で囲った箇所に注目してほしい. 一つのジョブが投入されると,それは SUBMITTED という状態を経て RUNNABLE という状態に遷移する. RUNNABLE とは, ジョブを実行するためのインスタンスが Compute environment に不足しているため,新たなインスタンスが起動されるのを待っている状態に相当する. インスタンスの準備が整うと,ジョブの状態は STARTING を経て RUNNING に至る.

    次に,ジョブのステータスが RUNNING のときの Compute environment の Desired vCPU を見てみよう (figure_title で紫で囲った箇所). ここで 4 と表示されているのは, g4dn.xlarge インスタンス一つ分の vCPU の数である. ジョブの投入に応じて,それを実行するのに最低限必要な EC2 インスタンスが起動されたことが確認できる (興味のある人は, EC2 コンソールも同時に覗いてみるとよい).

    しばらく経つと,ジョブの状態は RUNNING から SUCCEEDED (あるいは何らかの理由でエラーが発生したときには FAILED) に遷移する. 今回のハンズオンで使っている MNIST の学習はだいたい 10 分くらいで完了するはずである. ジョブの状態が SUCCEEDED になるまで見届けよう.

    ジョブが完了すると,学習の結果 (エポックごとの Loss と Accuracy を記録した CSV ファイル) は S3 に保存される. AWS コンソールからこれを確認しよう.

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    python
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    python
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    -
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    -
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    -
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    -
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    -
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    -
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    python
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    python
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    複数のジョブを同時投入したときの Job 一覧

    今度は EC2 コンソールを見てみよう. 左のメニューから Instances を選択すると, figure_title に示すような起動中のインスタンスの一覧が表示される. g4dn.xlarge が 9 台稼働しているのが確認できる. Batch がジョブの投下に合わせて必要な数のインスタンスを起動してくれたのだ!

    複数のジョブを同時投入したときの EC2 インスタンスの一覧

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    python
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    -
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    -
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    -
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    -
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    -
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    -
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    今回のパラメータサーチは勉強用に極めて単純化されたものである点は承知いただきたい.

    たとえば,今回は学習率が 0.1 が最も良いとされたが,それは訓練のエポックを 100 に限定しているからかもしれない. 学習率が低いとその分訓練に必要なエポック数も多くなる. 訓練のエポック数をもっと増やせばまた違った結果が観察される可能性はある.

    また,今回は MNIST の訓練データ 60,000 枚のうち, 48,000 枚を訓練データ,残り 12,000 枚を検証データとして用いた. この分割は乱数を固定してランダムに行ったが,もしこの分割によるデータのバイアスを気にするならば, k 個の異なる学習・検証データの分割をあらかじめ用意して,複数回モデルの評価を行う (k-fold cross-validation) 方法も,より精緻なアプローチとして考えられる.

    以上のようにして, CNN を用いた MNIST 分類モデルのハイパーパラメータの最適化の一連の流れを体験した. AWS Batch を利用することで,比較的少ないプログラミングで,動的に EC2 クラスターを制御し,並列にジョブを処理するシステムが構築できた. ここまで EC2 を使いこなすことができれば,多くの問題を自力で解くことが可能になるだろう!

    スタックの削除

    これにて,本ハンズオンは終了である.最後にスタックを削除しよう. 今回のスタックを削除するにあたり,ECR に配置された Docker のイメージは手動で削除されなければならない (これをしないと, cdk destroy を実行したときにエラーになってしまう. これは CloudFormation の仕様なので従うしかない).

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, (#sec_jupyter_and_deep_learning) で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを (#sec_fargate_qabot) を参考に構築する.

    実際,本書ではこの流れに沿って演習を進めてきた. MNIST タスクを解くモデルを,最初 Jupyter Notebook を使用して実験し,そのコードをほとんどそのまま Docker にパッケージし, AWS Batch を用いてハイパーパラメータサーチを行った. このサイクルを繰り返すことで,クラウドを最大限に活用した機械学習アプリケーションの開発を進めることができる.

    クラウドを活用した機械学習アプリケーションの開発フロー

    小括

    ここまでが,本書第二部の内容である. 第一部に引き続き盛りだくさんの内容であったが,ついてこれたであろうか?

    第二部ではまず最初に,深層学習の計算をクラウドで実行するため, GPU 搭載型の EC2 インスタンスの起動について解説した. さらに,ハンズオンでは,クラウドに起動した仮想サーバーを使って MNIST 文字認識タスクを解くニューラルネットを訓練した ( (#sec_jupyter_and_deep_learning)).

    また,より大規模な機械学習アプリケーションを作るための手段として, Docker と ECS によるクラスターの初歩を説明した ( (#sec_docker_introduction)). その応用として,英語で与えられた文章問題への回答を自動で生成するボットをクラウドに展開した ( (#sec_fargate_qabot)). タスクの投入に応じて動的に計算リソースが作成・削除される様子を実際に体験できただろう.

    さらに, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する では AWS Batch を用いてニューラルネットの学習を並列に実行する方法を紹介した. ここで紹介した方法は,ミニマムであるが,計算機システムを大規模化していくためのエッセンスが網羅されている. これらのハンズオン体験から,クラウド技術を応用してどのように現実世界の問題を解いていくのか,なんとなくイメージが伝わっただろうか?

    本書の第三部では,さらにレベルアップし,サーバーレスアーキテクチャという最新のクラウドの設計手法について解説する. その応用として,ハンズオンでは簡単な SNS サービスをゼロから実装する. 引き続きクラウドの最先端の世界を楽しんでいこう!

    ',162);function N(R,P,T,U,W,I){const n=a;return k(),D("div",null,[w,C(n,{readTime:"20",words:"5k"}),x])}const M=v(j,[["render",N]]);export{X as __pageData,M as default}; diff --git a/assets/development_aws_aws-batch.md.de2d649a.lean.js b/assets/development_aws_aws-batch.md.de2d649a.lean.js deleted file mode 100644 index 36cd2d87..00000000 --- a/assets/development_aws_aws-batch.md.de2d649a.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as o,c as e,d as t,e as c,f as r,g as y,h as i,i as u,j as b,k as d,l as m,m as B,n as A,o as h,p as _,q as g,r as f,s as q}from"./chunks/cloud_development.e43e5d4a.js";import{_ as v,o as k,c as D,H as C,k as s,a as E,Q as S}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const X=JSON.parse('{"title":"Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/aws-batch.md","filePath":"development/aws/aws-batch.md","lastUpdated":1695377563000}'),j={name:"development/aws/aws-batch.md"},w=s("h1",{id:"hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する",tabindex:"-1"},[E("Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する "),s("a",{class:"header-anchor",href:"#hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する","aria-label":'Permalink to "Hands-on \\#4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する"'},"​")],-1),x=S("",162);function N(R,P,T,U,W,I){const n=a;return k(),D("div",null,[w,C(n,{readTime:"20",words:"5k"}),x])}const M=v(j,[["render",N]]);export{X as __pageData,M as default}; diff --git a/assets/development_aws_aws-get-started.md.5e1dfdb2.js b/assets/development_aws_aws-get-started.md.5e1dfdb2.js new file mode 100644 index 00000000..c36db7f7 --- /dev/null +++ b/assets/development_aws_aws-get-started.md.5e1dfdb2.js @@ -0,0 +1,149 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,a as p,b as l,c as e,d as t,e as r,f as c,g as y,h as i,i as u,j as A}from"./chunks/iac.2263bc12.js";import{_ as C,a as d}from"./chunks/VPC.e1acca4d.js";import{_ as F,o as D,c as m,H as b,k as s,a as q,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"AWS 入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/aws-get-started.md","filePath":"development/aws/aws-get-started.md","lastUpdated":1699051935000}'),B={name:"development/aws/aws-get-started.md"},g=s("h1",{id:"aws-入門",tabindex:"-1"},[q("AWS 入門 "),s("a",{class:"header-anchor",href:"#aws-入門","aria-label":'Permalink to "AWS 入門"'},"​")],-1),E=h('

    AWS とは?

    本書では,クラウドの実践を行うプラットフォームとして, AWS を用いる. 実践にあたって,最低限必要な AWS の知識を本章では解説しよう.

    AWS (Amazon Web Services) は Amazon 社が提供する総合的なクラウドプラットフォームである. AWS は Amazon 社が持つ膨大な計算リソースを貸し出すクラウドサービスとして,2006 年に誕生した. 2021 年では,クラウドプロバイダーとして最大のマーケットシェア (約 32%) を保持している (参照). Netflix や Slack をはじめとした多くのウェブ関連のサービスで,一部または全てのサーバーリソースが AWS から提供されているとのことである. よって,知らないうちに AWS の恩恵にあずかっている人も少なくないはずだ.

    最大のシェアをもつだけに,機能・サービスの幅広さはほかのクラウドプラットフォームと比べ抜きんでている. また,利用者数が多いことを反映して,公式あるいはサードパーティによる技術紹介記事が数多くウェブ上に存在しているだけでなく,ライブラリのユーザーコミュニティも大きく問題解決が捗るのも魅力の一つだ. 初期のころウェブビジネスを行う企業がユーザーの大半を占めていたが,最近は大学などでの科学研究用途としても頻繁に用いられるようになってきている.

    AWS の機能・サービス

    figure_title は,執筆時点において AWS で提供されている主要な機能・サービスの一覧である.

    AWSで提供されている主要なサービス一覧

    計算,ストレージ,データベース,ネットワーク,セキュリティなど,クラウドの構築に必要な様々な要素が独立したコンポーネントとして提供されている. 基本的に,これらを組み合わせることで一つのクラウドシステムができあがる.

    また,機械学習・音声認識・AR/VR など,特定のアプリケーションにパッケージ済みのサービスも提供されている. これらを合計すると全部で 170 個以上のサービスが提供されているとのことである (参照).

    AWS の初心者が陥りがちなのは,大量のサービスの数に圧倒され,どこから手をつけたらよいのかわからなくなる,という状況である. たくさんのサービスの中から,どのサービスをどの順番で学んでいったらいいのか,その道筋すら明らかでなく,大きな参入障壁となっていることは間違いない. だが実のところ, AWS の基本的な構成要素はそのうちの数個のみに限られる. 基本要素となる機能の使い方を知れば, AWS のおおよそのリソースを使いこなすことが可能になる. ほかの機能の多くは,基本の要素を組み合わせて特定のアプリケーションに特化したパッケージとして AWS が用意したものである. そのポイントを認知することが, AWS の学習の最初のステップである.

    ここでは, AWS 上でクラウドシステムを構築するときの基本となる構成要素を列挙する. これらは後のハンズオンで実際にプログラムを書きながら体験する. 現時点では,名前だけでも頭の片隅に記憶してもらえればよい.

    計算

    S3 EC2 (Elastic Compute Cloud) 様々なスペックの仮想マシンを作成し,計算を実行することができる. クラウドの最も基本となる構成要素である. (#sec_first_ec2), (#sec_jupyter_and_deep_learning), (#sec_aws_batch) で詳しく触れる.

    S3 Lambda Function as a Service (FaaS) とよばれる,小さな計算をサーバーなしで実行するためのサービス. サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    ストレージ

    S3EBS (Elastic Block Store) EC2 に付与することのできる仮想データドライブ. いわゆる"普通の"(一般的な OS で使われている)ファイルシステムを思い浮かべてくれたらよい.

    S3

    S3 (Simple Storage Service) Object Storage とよばれる,API を使ってデータの読み書きを行う,いうなれば”クラウド・ネイティブ”なデータの格納システムである. サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    データベース

    S3

    DynamoDB NoSQL 型のデータベースサービス (知っている人は mongoDB などを思い浮かべたらよい). サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    ネットワーク

    S3 VPC(Virtual Private Cloud) AWS 上に仮想ネットワーク環境を作成し,仮想サーバー間の接続を定義したり,外部からのアクセスなどを管理する. EC2 は VPC の内部に配置されなければならない.

    API Gateway S3

    API のエンドポイントとバックエンドのサービス (Lambda など) を接続する際に用いる,リバースプロキシとしての役割を担う. (#sec_bashoutter) で詳しく解説する.

    Region と Availability Zone

    AWS を使用する際に知っておかなければならない重要な概念として, リージョン (Region)Availability Zone (AZ) がある (figure_title). 以下ではこの概念について簡単に記述する.

    AWSにおける Region と Availability Zones

    リージョン (Region) とは,おおまかに言うとデータセンターの所在地のことである. 執筆時点において, AWS は世界の 25 の国と地域でデータセンターを所有している. figure_title は執筆時点で利用できるリージョンの世界地図を示している. 日本では東京と大阪にデータセンターがある. 各リージョンには固有の ID がついており,例えば東京は ap-northeast-1, 米国オハイオ州は us-east-2,などと定義されている.

    Regions in AWS(出典: https://aws.amazon.com/about-aws/global-infrastructure/)

    AWS コンソールにログインすると,画面右上のメニューバーでリージョンを選択することができる(figure_title, 赤丸で囲った箇所). EC2, S3 などの AWS のリソースは,リージョンごとに完全に独立である. したがって,リソースを新たにデプロイする際,あるいはデプロイ済みのリソースを閲覧する際は,コンソールのリージョンが正しく設定されているか,確認する必要がある. ウェブビジネスを展開する場合などは,世界の各地にクラウドを展開する必要があるが,個人的な研究用途として用いる場合は,最寄りのリージョン (i.e. 東京) を使えば基本的に問題ない.

    AWSコンソールでリージョンを選択

    Avaialibity Zone (AZ) とは,リージョン内で地理的に隔離されたデータセンターのことである. それぞれのリージョンは 2 個以上の AZ を有しており,もし一つの AZ で火災や停電などが起きた場合でも,ほかの AZ がその障害をカバーすることができる. また, AZ 間は高速な AWS 専用ネットワーク回線で結ばれているため, AZ 間のデータ転送は極めて早い. AZ は,ビジネスなどでサーバーダウンが許容されない場合などに注意すべき概念であり,個人的な用途で使う限りにおいてはあまり深く考慮する必要はない.言葉の意味だけ知っておけば十分である.

    AWS を使用する際,どこのリージョンを指定するのがよいのだろうか? インターネットの接続速度の観点からは,地理的に一番近いリージョンを使用するのが一般的によいだろう. 一方, EC2 の利用料などはリージョンごとに価格設定が若干 (10-20%程度) 異なる. したがって,自分が最も頻繁に利用するサービスの価格が最も安く設定されているリージョンを選択する,というのも重要な視点である. また,いくつかのサービスは,特定のリージョンで利用できない場合もある. これらのポイントから総合的に判断して使用するリージョンを決めると良い.

    AWS Educate を利用している読者へ

    執筆時点において,AWS Educate による Starter Account を使用している場合は us-east-1 region のみ利用できる (参照).

    AWS でのクラウド開発

    AWS のクラウドの全体像がわかってきたところで,次のトピックとして,どのようにして AWS 上にクラウドの開発を行い,展開していくかについての概略を解説しよう.

    AWS のリソースを追加・編集・削除するなどの操作を実行するには,コンソールを用いる方法と,API を用いる方法の,二つの経路がある.

    コンソール画面からリソースを操作する

    AWS のアカウントにログインすると,まず最初に表示されるのがAWS コンソールである (figure_title).

    AWSマネージメントコンソール画面

    コンソールを使うことで, EC2 のインスタンスを立ち上げたり,S3 のデータを追加・削除したり,ログを閲覧したりなど,AWS 上のあらゆるリソースの操作を GUI (Graphical User Interface) を通して実行することができる. 初めて触る機能をポチポチと試したり,デバッグを行うときなどにとても便利である

    コンソールはさらっと機能を試したり,開発中のクラウドのデバッグをするときには便利なのであるが,実際にクラウドの開発をする場面でこれを直接いじることはあまりない. むしろ,次に紹介する API を使用して,プログラムとしてクラウドのリソースを記述することで開発を行うのが一般的である. そのような理由で,本書では AWS コンソールを使った AWS の使い方はあまり触れない. AWS のドキュメンテーションには,たくさんの チュートリアル が用意されており,コンソール画面から様々な操作を行う方法が記述されているので,興味がある読者はそちらを参照されたい.

    API からリソースを操作する

    API (Application Programming Interface) を使うことで,コマンドを AWS に送信し,クラウドのリソースの操作をすることができる. API とは,端的に言えば AWS が公開しているコマンドの一覧であり,GET, POST, DELETE などの REST API から構成されている (REST API については (#sec_rest_api) で簡単に解説する). が,直接 REST API を入力するのは面倒であるので,その手間を解消するための様々なツールが提供されている.

    例えば, AWS CLI は, UNIX コンソールから AWS API を実行するための CLI (Command Line Interface) である. CLI に加えて,いろいろなプログラミング言語での SDK (Software Development Kit) が提供されている.以下に一例を挙げる.

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    python
    import boto3
    +
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    +
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン ( (#sec_first_ec2)) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    python
    import boto3
    +
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)
    import boto3
    +
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    AWS CLI のインストールについては, (#aws_cli_install) を参照.

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは (#aws_cli_install) を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://\${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://\${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    sh
    $ aws s3 ls
    +
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    +
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    sh
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://\${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://\${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    sh
    $ aws s3 ls "s3://\${bucketName}" --human-readable
    +
    +2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://\${bucketName}" --human-readable
    +
    +2020-06-07 23:54:19   13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    sh
    $ aws s3 rb "s3://\${bucketName}" --force
    $ aws s3 rb "s3://\${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    AWS 上のあらゆるリソースには, Amazon Resource Name (ARN) という固有の ID が付与されている. ARN は arn:aws:s3:::my_bucket/ のようなフォーマットで記述され,ARN を使用することで,特定の AWS リソース (S3 のバケットや EC2 のインスタンス) を一意的に参照することができる.

    S3 バケットや EC2 インスタンスなどには ARN に加えて,人間が読みやすい名前を定義することも可能である. この場合は,ARN または名前のどちらを用いても同じリソースを参照することが可能である.

    CloudFormation と AWS CDK

    CloudFormation による Infrastructure as Code (IaC)

    前節で述べたように,AWS API を使うことでクラウドのあらゆるリソースの作成・管理が可能である. よって,原理上は, API のコマンドを組み合わせていくことで,自分の作りたいクラウドを設計することができる.

    しかし,ここで実用上考慮しなければならない点が一つある. AWS API には大きく分けて,リソースを操作するコマンドと,タスクを実行するコマンドがあることである (figure_title).

    AWS APIはリソースを操作するコマンドとタスクを実行するコマンドに大きく分けられる.リソースを記述・管理するのに使われるのが, CloudFormation と CDK である.

    リソースを操作するとは,EC2 のインスタンスを起動したり,S3 のバケットを作成したり,データベースに新たなテーブルを追加する,などの静的なリソースを準備する 操作を指す. "ハコ"を作る操作とよんでも良いだろう. このようなコマンドは,クラウドのデプロイ時にのみ,一度だけ実行されればよい

    タスクを実行するコマンド とは, EC2 のインスタンスにジョブを投入したり, S3 のバケットにデータを読み書きするなどの操作を指す. これは, EC2 や S3 などのリソース ("ハコ") を前提として,その内部で実行されるべき計算を記述するものである. 前者に比べてこちらは動的な操作を担当する,と捉えることもできる.

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    json
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\\n",
    +                     "yum update -y aws-cfn-bootstrap\\n",
    +
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\\n",
    +
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\\n",
    +                     "yum update -y aws-cfn-bootstrap\\n",
    +
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\\n",
    +
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    python
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
    +
    +class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
    +
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
    +
    +class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
    +
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

    • AWS CDK Examples: CDK を使ったプロジェクトの例が多数紹介されている. ここにある例をテンプレートに自分のアプリケーションの開発を進めるとよい.
    `,108);function S(_,f,k,v,w,W){const a=n;return D(),m("div",null,[g,b(a,{readTime:"9",words:"2.4k"}),E])}const K=F(B,[["render",S]]);export{$ as __pageData,K as default}; diff --git a/assets/development_aws_aws-get-started.md.5e1dfdb2.lean.js b/assets/development_aws_aws-get-started.md.5e1dfdb2.lean.js new file mode 100644 index 00000000..2541ddb1 --- /dev/null +++ b/assets/development_aws_aws-get-started.md.5e1dfdb2.lean.js @@ -0,0 +1 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,a as p,b as l,c as e,d as t,e as r,f as c,g as y,h as i,i as u,j as A}from"./chunks/iac.2263bc12.js";import{_ as C,a as d}from"./chunks/VPC.e1acca4d.js";import{_ as F,o as D,c as m,H as b,k as s,a as q,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"AWS 入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/aws-get-started.md","filePath":"development/aws/aws-get-started.md","lastUpdated":1699051935000}'),B={name:"development/aws/aws-get-started.md"},g=s("h1",{id:"aws-入門",tabindex:"-1"},[q("AWS 入門 "),s("a",{class:"header-anchor",href:"#aws-入門","aria-label":'Permalink to "AWS 入門"'},"​")],-1),E=h("",108);function S(_,f,k,v,w,W){const a=n;return D(),m("div",null,[g,b(a,{readTime:"9",words:"2.4k"}),E])}const K=F(B,[["render",S]]);export{$ as __pageData,K as default}; diff --git a/assets/development_aws_aws-get-started.md.e1a56953.js b/assets/development_aws_aws-get-started.md.e1a56953.js deleted file mode 100644 index 70ec3808..00000000 --- a/assets/development_aws_aws-get-started.md.e1a56953.js +++ /dev/null @@ -1,149 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,a as l,b as p,c as e,d as t,e as r,f as c,g as y,h as i,i as u,j as A}from"./chunks/iac.2263bc12.js";import{_ as d,a as m}from"./chunks/VPC.e1acca4d.js";import{_ as b,o as B,c as q,H as h,k as s,a as g,Q as S}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const F=JSON.parse('{"title":"AWS 入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/aws-get-started.md","filePath":"development/aws/aws-get-started.md","lastUpdated":1695377563000}'),_={name:"development/aws/aws-get-started.md"},f=s("h1",{id:"aws-入門",tabindex:"-1"},[g("AWS 入門 "),s("a",{class:"header-anchor",href:"#aws-入門","aria-label":'Permalink to "AWS 入門"'},"​")],-1),C=S('

    AWS とは?

    本書では,クラウドの実践を行うプラットフォームとして, AWS を用いる. 実践にあたって,最低限必要な AWS の知識を本章では解説しよう.

    AWS (Amazon Web Services) は Amazon 社が提供する総合的なクラウドプラットフォームである. AWS は Amazon 社が持つ膨大な計算リソースを貸し出すクラウドサービスとして,2006 年に誕生した. 2021 年では,クラウドプロバイダーとして最大のマーケットシェア (約 32%) を保持している (参照). Netflix や Slack をはじめとした多くのウェブ関連のサービスで,一部または全てのサーバーリソースが AWS から提供されているとのことである. よって,知らないうちに AWS の恩恵にあずかっている人も少なくないはずだ.

    最大のシェアをもつだけに,機能・サービスの幅広さはほかのクラウドプラットフォームと比べ抜きんでている. また,利用者数が多いことを反映して,公式あるいはサードパーティによる技術紹介記事が数多くウェブ上に存在しているだけでなく,ライブラリのユーザーコミュニティも大きく問題解決が捗るのも魅力の一つだ. 初期のころウェブビジネスを行う企業がユーザーの大半を占めていたが,最近は大学などでの科学研究用途としても頻繁に用いられるようになってきている.

    AWS の機能・サービス

    figure_title は,執筆時点において AWS で提供されている主要な機能・サービスの一覧である.

    AWSで提供されている主要なサービス一覧

    計算,ストレージ,データベース,ネットワーク,セキュリティなど,クラウドの構築に必要な様々な要素が独立したコンポーネントとして提供されている. 基本的に,これらを組み合わせることで一つのクラウドシステムができあがる.

    また,機械学習・音声認識・AR/VR など,特定のアプリケーションにパッケージ済みのサービスも提供されている. これらを合計すると全部で 170 個以上のサービスが提供されているとのことである (参照).

    AWS の初心者が陥りがちなのは,大量のサービスの数に圧倒され,どこから手をつけたらよいのかわからなくなる,という状況である. たくさんのサービスの中から,どのサービスをどの順番で学んでいったらいいのか,その道筋すら明らかでなく,大きな参入障壁となっていることは間違いない. だが実のところ, AWS の基本的な構成要素はそのうちの数個のみに限られる. 基本要素となる機能の使い方を知れば, AWS のおおよそのリソースを使いこなすことが可能になる. ほかの機能の多くは,基本の要素を組み合わせて特定のアプリケーションに特化したパッケージとして AWS が用意したものである. そのポイントを認知することが, AWS の学習の最初のステップである.

    ここでは, AWS 上でクラウドシステムを構築するときの基本となる構成要素を列挙する. これらは後のハンズオンで実際にプログラムを書きながら体験する. 現時点では,名前だけでも頭の片隅に記憶してもらえればよい.

    計算

    S3 EC2 (Elastic Compute Cloud) 様々なスペックの仮想マシンを作成し,計算を実行することができる. クラウドの最も基本となる構成要素である. (#sec_first_ec2), (#sec_jupyter_and_deep_learning), (#sec_aws_batch) で詳しく触れる.

    S3 Lambda Function as a Service (FaaS) とよばれる,小さな計算をサーバーなしで実行するためのサービス. サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    ストレージ

    S3EBS (Elastic Block Store) EC2 に付与することのできる仮想データドライブ. いわゆる"普通の"(一般的な OS で使われている)ファイルシステムを思い浮かべてくれたらよい.

    S3

    S3 (Simple Storage Service) Object Storage とよばれる,API を使ってデータの読み書きを行う,いうなれば”クラウド・ネイティブ”なデータの格納システムである. サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    データベース

    S3

    DynamoDB NoSQL 型のデータベースサービス (知っている人は mongoDB などを思い浮かべたらよい). サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    ネットワーク

    S3 VPC(Virtual Private Cloud) AWS 上に仮想ネットワーク環境を作成し,仮想サーバー間の接続を定義したり,外部からのアクセスなどを管理する. EC2 は VPC の内部に配置されなければならない.

    API Gateway S3

    API のエンドポイントとバックエンドのサービス (Lambda など) を接続する際に用いる,リバースプロキシとしての役割を担う. (#sec_bashoutter) で詳しく解説する.

    Region と Availability Zone

    AWS を使用する際に知っておかなければならない重要な概念として, リージョン (Region)Availability Zone (AZ) がある (figure_title). 以下ではこの概念について簡単に記述する.

    AWSにおける Region と Availability Zones

    リージョン (Region) とは,おおまかに言うとデータセンターの所在地のことである. 執筆時点において, AWS は世界の 25 の国と地域でデータセンターを所有している. figure_title は執筆時点で利用できるリージョンの世界地図を示している. 日本では東京と大阪にデータセンターがある. 各リージョンには固有の ID がついており,例えば東京は ap-northeast-1, 米国オハイオ州は us-east-2,などと定義されている.

    Regions in AWS(出典: https://aws.amazon.com/about-aws/global-infrastructure/)

    AWS コンソールにログインすると,画面右上のメニューバーでリージョンを選択することができる(figure_title, 赤丸で囲った箇所). EC2, S3 などの AWS のリソースは,リージョンごとに完全に独立である. したがって,リソースを新たにデプロイする際,あるいはデプロイ済みのリソースを閲覧する際は,コンソールのリージョンが正しく設定されているか,確認する必要がある. ウェブビジネスを展開する場合などは,世界の各地にクラウドを展開する必要があるが,個人的な研究用途として用いる場合は,最寄りのリージョン (i.e. 東京) を使えば基本的に問題ない.

    AWSコンソールでリージョンを選択

    Avaialibity Zone (AZ) とは,リージョン内で地理的に隔離されたデータセンターのことである. それぞれのリージョンは 2 個以上の AZ を有しており,もし一つの AZ で火災や停電などが起きた場合でも,ほかの AZ がその障害をカバーすることができる. また, AZ 間は高速な AWS 専用ネットワーク回線で結ばれているため, AZ 間のデータ転送は極めて早い. AZ は,ビジネスなどでサーバーダウンが許容されない場合などに注意すべき概念であり,個人的な用途で使う限りにおいてはあまり深く考慮する必要はない.言葉の意味だけ知っておけば十分である.

    AWS を使用する際,どこのリージョンを指定するのがよいのだろうか? インターネットの接続速度の観点からは,地理的に一番近いリージョンを使用するのが一般的によいだろう. 一方, EC2 の利用料などはリージョンごとに価格設定が若干 (10-20%程度) 異なる. したがって,自分が最も頻繁に利用するサービスの価格が最も安く設定されているリージョンを選択する,というのも重要な視点である. また,いくつかのサービスは,特定のリージョンで利用できない場合もある. これらのポイントから総合的に判断して使用するリージョンを決めると良い.

    AWS Educate を利用している読者へ

    執筆時点において,AWS Educate による Starter Account を使用している場合は us-east-1 region のみ利用できる (参照).

    AWS でのクラウド開発

    AWS のクラウドの全体像がわかってきたところで,次のトピックとして,どのようにして AWS 上にクラウドの開発を行い,展開していくかについての概略を解説しよう.

    AWS のリソースを追加・編集・削除するなどの操作を実行するには,コンソールを用いる方法と,API を用いる方法の,二つの経路がある.

    コンソール画面からリソースを操作する

    AWS のアカウントにログインすると,まず最初に表示されるのがAWS コンソールである (figure_title).

    AWSマネージメントコンソール画面

    コンソールを使うことで, EC2 のインスタンスを立ち上げたり,S3 のデータを追加・削除したり,ログを閲覧したりなど,AWS 上のあらゆるリソースの操作を GUI (Graphical User Interface) を通して実行することができる. 初めて触る機能をポチポチと試したり,デバッグを行うときなどにとても便利である

    コンソールはさらっと機能を試したり,開発中のクラウドのデバッグをするときには便利なのであるが,実際にクラウドの開発をする場面でこれを直接いじることはあまりない. むしろ,次に紹介する API を使用して,プログラムとしてクラウドのリソースを記述することで開発を行うのが一般的である. そのような理由で,本書では AWS コンソールを使った AWS の使い方はあまり触れない. AWS のドキュメンテーションには,たくさんの チュートリアル が用意されており,コンソール画面から様々な操作を行う方法が記述されているので,興味がある読者はそちらを参照されたい.

    API からリソースを操作する

    API (Application Programming Interface) を使うことで,コマンドを AWS に送信し,クラウドのリソースの操作をすることができる. API とは,端的に言えば AWS が公開しているコマンドの一覧であり,GET, POST, DELETE などの REST API から構成されている (REST API については (#sec_rest_api) で簡単に解説する). が,直接 REST API を入力するのは面倒であるので,その手間を解消するための様々なツールが提供されている.

    例えば, AWS CLI は, UNIX コンソールから AWS API を実行するための CLI (Command Line Interface) である. CLI に加えて,いろいろなプログラミング言語での SDK (Software Development Kit) が提供されている.以下に一例を挙げる.

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    python
    import boto3
    -
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    -
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン ( (#sec_first_ec2)) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    python
    import boto3
    -
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    import boto3
    -
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    AWS CLI のインストールについては, (#aws_cli_install) を参照.

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは (#aws_cli_install) を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://\${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://\${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    sh
    $ aws s3 ls
    -
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    -
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    sh
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://\${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://\${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    sh
    $ aws s3 ls "s3://\${bucketName}" --human-readable
    -
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://\${bucketName}" --human-readable
    -
    -2020-06-07 23:54:19   13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    sh
    $ aws s3 rb "s3://\${bucketName}" --force
    $ aws s3 rb "s3://\${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    AWS 上のあらゆるリソースには, Amazon Resource Name (ARN) という固有の ID が付与されている. ARN は arn:aws:s3:::my_bucket/ のようなフォーマットで記述され,ARN を使用することで,特定の AWS リソース (S3 のバケットや EC2 のインスタンス) を一意的に参照することができる.

    S3 バケットや EC2 インスタンスなどには ARN に加えて,人間が読みやすい名前を定義することも可能である. この場合は,ARN または名前のどちらを用いても同じリソースを参照することが可能である.

    CloudFormation と AWS CDK

    CloudFormation による Infrastructure as Code (IaC)

    前節で述べたように,AWS API を使うことでクラウドのあらゆるリソースの作成・管理が可能である. よって,原理上は, API のコマンドを組み合わせていくことで,自分の作りたいクラウドを設計することができる.

    しかし,ここで実用上考慮しなければならない点が一つある. AWS API には大きく分けて,リソースを操作するコマンドと,タスクを実行するコマンドがあることである (figure_title).

    AWS APIはリソースを操作するコマンドとタスクを実行するコマンドに大きく分けられる.リソースを記述・管理するのに使われるのが, CloudFormation と CDK である.

    リソースを操作するとは,EC2 のインスタンスを起動したり,S3 のバケットを作成したり,データベースに新たなテーブルを追加する,などの静的なリソースを準備する 操作を指す. "ハコ"を作る操作とよんでも良いだろう. このようなコマンドは,クラウドのデプロイ時にのみ,一度だけ実行されればよい

    タスクを実行するコマンド とは, EC2 のインスタンスにジョブを投入したり, S3 のバケットにデータを読み書きするなどの操作を指す. これは, EC2 や S3 などのリソース ("ハコ") を前提として,その内部で実行されるべき計算を記述するものである. 前者に比べてこちらは動的な操作を担当する,と捉えることもできる.

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    json
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\\n",
    -                     "yum update -y aws-cfn-bootstrap\\n",
    -
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\\n",
    -
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\\n",
    -                     "yum update -y aws-cfn-bootstrap\\n",
    -
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\\n",
    -
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    python
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    -
    -class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    -
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    -
    -class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    -
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

    • AWS CDK Examples: CDK を使ったプロジェクトの例が多数紹介されている. ここにある例をテンプレートに自分のアプリケーションの開発を進めるとよい.
    `,108);function k(v,w,W,D,I,x){const a=n;return B(),q("div",null,[f,h(a,{readTime:"9",words:"2.4k"}),C])}const $=b(_,[["render",k]]);export{F as __pageData,$ as default}; diff --git a/assets/development_aws_aws-get-started.md.e1a56953.lean.js b/assets/development_aws_aws-get-started.md.e1a56953.lean.js deleted file mode 100644 index 3f40092f..00000000 --- a/assets/development_aws_aws-get-started.md.e1a56953.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,a as l,b as p,c as e,d as t,e as r,f as c,g as y,h as i,i as u,j as A}from"./chunks/iac.2263bc12.js";import{_ as d,a as m}from"./chunks/VPC.e1acca4d.js";import{_ as b,o as B,c as q,H as h,k as s,a as g,Q as S}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const F=JSON.parse('{"title":"AWS 入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/aws-get-started.md","filePath":"development/aws/aws-get-started.md","lastUpdated":1695377563000}'),_={name:"development/aws/aws-get-started.md"},f=s("h1",{id:"aws-入門",tabindex:"-1"},[g("AWS 入門 "),s("a",{class:"header-anchor",href:"#aws-入門","aria-label":'Permalink to "AWS 入門"'},"​")],-1),C=S("",108);function k(v,w,W,D,I,x){const a=n;return B(),q("div",null,[f,h(a,{readTime:"9",words:"2.4k"}),C])}const $=b(_,[["render",k]]);export{F as __pageData,$ as default}; diff --git a/assets/development_aws_closing.md.cf9dad64.js b/assets/development_aws_closing.md.0cdd4f54.js similarity index 91% rename from assets/development_aws_closing.md.cf9dad64.js rename to assets/development_aws_closing.md.0cdd4f54.js index b93aeb01..c27910c8 100644 --- a/assets/development_aws_closing.md.cf9dad64.js +++ b/assets/development_aws_closing.md.0cdd4f54.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as s,c as n,H as r,k as e,a as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"まとめ","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/closing.md","filePath":"development/aws/closing.md","lastUpdated":1695377563000}'),d={name:"development/aws/closing.md"},i=e("h1",{id:"まとめ",tabindex:"-1"},[c("まとめ "),e("a",{class:"header-anchor",href:"#まとめ","aria-label":'Permalink to "まとめ"'},"​")],-1);function l(m,p,_,f,h,g){const a=t;return s(),n("div",null,[i,r(a,{readTime:"1",words:"0"})])}const k=o(d,[["render",l]]);export{$ as __pageData,k as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as s,c as n,H as r,k as e,a as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"まとめ","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/closing.md","filePath":"development/aws/closing.md","lastUpdated":1699051935000}'),d={name:"development/aws/closing.md"},i=e("h1",{id:"まとめ",tabindex:"-1"},[c("まとめ "),e("a",{class:"header-anchor",href:"#まとめ","aria-label":'Permalink to "まとめ"'},"​")],-1);function l(m,p,_,f,h,g){const a=t;return s(),n("div",null,[i,r(a,{readTime:"1",words:"0"})])}const k=o(d,[["render",l]]);export{$ as __pageData,k as default}; diff --git a/assets/development_aws_closing.md.cf9dad64.lean.js b/assets/development_aws_closing.md.0cdd4f54.lean.js similarity index 91% rename from assets/development_aws_closing.md.cf9dad64.lean.js rename to assets/development_aws_closing.md.0cdd4f54.lean.js index b93aeb01..c27910c8 100644 --- a/assets/development_aws_closing.md.cf9dad64.lean.js +++ b/assets/development_aws_closing.md.0cdd4f54.lean.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as s,c as n,H as r,k as e,a as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"まとめ","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/closing.md","filePath":"development/aws/closing.md","lastUpdated":1695377563000}'),d={name:"development/aws/closing.md"},i=e("h1",{id:"まとめ",tabindex:"-1"},[c("まとめ "),e("a",{class:"header-anchor",href:"#まとめ","aria-label":'Permalink to "まとめ"'},"​")],-1);function l(m,p,_,f,h,g){const a=t;return s(),n("div",null,[i,r(a,{readTime:"1",words:"0"})])}const k=o(d,[["render",l]]);export{$ as __pageData,k as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as s,c as n,H as r,k as e,a as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"まとめ","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/closing.md","filePath":"development/aws/closing.md","lastUpdated":1699051935000}'),d={name:"development/aws/closing.md"},i=e("h1",{id:"まとめ",tabindex:"-1"},[c("まとめ "),e("a",{class:"header-anchor",href:"#まとめ","aria-label":'Permalink to "まとめ"'},"​")],-1);function l(m,p,_,f,h,g){const a=t;return s(),n("div",null,[i,r(a,{readTime:"1",words:"0"})])}const k=o(d,[["render",l]]);export{$ as __pageData,k as default}; diff --git a/assets/development_aws_cloud.md.e679b136.js b/assets/development_aws_cloud.md.148d68f2.js similarity index 99% rename from assets/development_aws_cloud.md.e679b136.js rename to assets/development_aws_cloud.md.148d68f2.js index 0f84f8c4..aa06703a 100644 --- a/assets/development_aws_cloud.md.e679b136.js +++ b/assets/development_aws_cloud.md.148d68f2.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,a as t,b as i,c as p}from"./chunks/terminal.94539704.js";import{_ as n,o as s,c as l,H as c,k as o,a as g,Q as d}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"クラウド概論","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/cloud.md","filePath":"development/aws/cloud.md","lastUpdated":1695377563000}'),u={name:"development/aws/cloud.md"},_=o("h1",{id:"クラウド概論",tabindex:"-1"},[g("クラウド概論 "),o("a",{class:"header-anchor",href:"#クラウド概論","aria-label":'Permalink to "クラウド概論"'},"​")],-1),f=d('

    クラウドとは?

    Cloud

    クラウドとはなにか? クラウドという言葉は,それ自身がとても広い意味をもつので,厳密な定義付けを行うことは難しい.

    学術的な意味でのクラウドの定義づけをするとしたら,NIST(米国・国立標準技術研究所) による The NIST Definition of Cloud Computing が引用されることが多い. ここに記載されたクラウドの定義・モデルを図示したのが figure_title である.

    The NIST Definition of Cloud Computing

    これによると,クラウドとは以下の要件が満たされたハードウェア/ソフトウェアの総体のことをいう.

    • On-demand self-service 利用者のリクエストに応じて計算資源が自動的に割り当てられる.

    • Broad network access 利用者はネットワークを通じてクラウドにアクセスできる.

    • Resource pooling クラウドプロバイダーは,所有する計算資源を分割することで複数の利用者に計算資源を割り当てる.

    • Rapid elasticity 利用者のリクエストに応じて,迅速に計算資源の拡大あるいは縮小を行うことができる.

    • Measured service 計算資源の利用量を計測・監視することができる.

    …と,いわれても抽象的でよくわからないかもしれない.もう少し具体的な話をする.

    個人が所有する計算機で, CPU をアップグレードしようと思ったら,物理的に筐体を開け,CPU ソケットを露出させ,新しい CPU に交換する必要があるだろう. あるいは,ストレージがいっぱいになってしまったら,古いディスクを抜き取り,新しいディスクを挿入する必要がある. 計算機の場所を移動させたときには,新しい部屋の LAN ケーブルを差し込まないとネットワークには接続できない.

    クラウドでは,これらの操作がプログラムからのコマンドによって実行できる. CPU が 1000 個欲しいと思ったならば,そのようにクラウドプロバイダーにリクエストを送れば良い. すると,数分もしないうちに 1000 CPU の計算資源が割り当てられる. ストレージを 1TB から 10TB に拡張しようと思ったならば,そのようにコマンドを送ればよい (これは,Google Drive や Dropbox などのサービスなどで馴染みのある人も多いだろう). 計算資源を使い終わったら,そのことをプロバイダーに伝えれば,割り当て分はすぐさま削除される. クラウドプロバイダーは,使った計算資源の量を正確にモニタリングしており,その量をもとに利用料金の計算が行われる.

    このように,クラウドの本質は物理的なハードウェアの仮想化・抽象化であり,利用者はコマンドを通じて,まるでソフトウェアの一部かのように,物理的なハードウェアの管理・運用を行うことができる. もちろん,背後では,データセンターに置かれた膨大な数の計算機が大量の電力を消費しながら稼働している. クラウドプロバイダーはデータセンターの計算資源を上手にやりくりし,ソフトウェアとしてのインターフェースをユーザーに提供することで,このような仮想化・抽象化を達成しているわけである. クラウドプロバイダーの視点からすると,大勢のユーザーに計算機を貸し出し,データセンターの稼働率を常時 100%に近づけることで,利益率の最大化を図っているのである.

    著者の言葉で,クラウドの重要な特性を定義するならば,以下のようになる.

    クラウドとは計算機ハードウェアの抽象化である.つまり,物理的なハードウェアをソフトウェアの一部かのように自在に操作・拡大・接続することを可能にする技術である.

    先述の The NIST Definition of Cloud Computing に戻ると,クラウドプロバイダーによるクラウドサービスの形態としては,次の三つが定義されている (figure_title).

    • Software as a Service (SaaS): クラウド上で実行されるアプリケーションをサービスとして利用者に提供する形態. 例として, Google Drive や Slack などが挙げられる. 利用者は,背後にあるクラウドのインフラ (ネットワークやサーバーなど) には直接触れず,アプリケーションとして提供されているクラウドサービスを享受する.

    • Platform as a Service (PaaS): 顧客の作成したアプリケーション (多くの場合データベースと API リクエスト処理を行うサーバーのコードから構成される) をデプロイする環境をサービスとして利用者に提供する形態. PaaS では利用者はクラウドのインフラに直接触れることはなく,計算負荷が増減した際のサーバーのスケーリングはクラウドプロバイダーによってなされる. 例としては, Google App Engine や Heroku などがある.

    • Infrastructure as a Service (IaaS): クラウド上の計算インフラストラクチャーを従量課金制で利用者に提供する形態. 利用者は必要なネットワーク・サーバー・ストレージをプロバイダーから借り受け,そこに自身のアプリケーションを展開し運用する. IaaS の例としては AWS EC2 などが挙げられる.

    本書が扱うのは,主に IaaS におけるクラウド開発である. すなわち,開発者がクラウドのインフラを直接操作し,所望のネットワーク・サーバー・ストレージなどを一から構成し,そこにアプリケーションを展開するというクラウド開発である. この意味において,クラウドの開発とはクラウドインフラストラクチャーを定義・展開するプログラムを構築するステップインフラ上で実際に走るアプリケーションを作成するステップの二つに分けることができる. この二つは,プログラマーの技術としてはある程度分業を行うことが可能であるが,最も効率化・最適化されたクラウドシステムを構築するためには両方の理解が必須である. 本書では,前者 (クラウドインフラの記述) に重きを置きつつ,アプリケーションレイヤーの話題も取り扱う. PaaS とは,開発者はアプリケーションレイヤーの開発に注力し,クラウドインフラの部分はクラウドプロバイダーに依存するという概念である. PaaS は,クラウドインフラの開発が不要になることで開発の時間が短縮されるが,細かなインフラの挙動はコントロールできないという限界がある. 本書では PaaS についてはとくに取り扱わない.

    SaaS は本書の文脈では開発による"成果物"と捉えられるだろう. すなわち, IaaS を構成するプログラムを作成し展開することによって,一般の人が利用できるようなウェブ上の計算サービスやデータベースを提供することが開発の最終ゴールである. 本書のハンズオンではその実例として,シンプルな SNS の作成 ( (#sec_bashoutter)) などの演習を提供する.

    なお,最近では Function as a Service (FaaS) やサーバーレスコンピューティングなども新たなクラウドのカテゴリとして認知されている. これらの概念については (#sec_intro_serverless) などの章で詳しく触れていく. 本書を読み進める中で明らかになるように,クラウドの技術は日進月歩である. 本書では実用的・教育的な観点から,従来的なクラウドの設計概念に触れたあと,サーバーレスなどの最新の技術も網羅するので,楽しみにしながら読み進めていただきたい.

    最後に,The NIST Definition of Cloud Computing によると,クラウドの運用形態について次のような定義がなされている (figure_title). 特定の組織・団体・企業の内部のみで使用されるクラウドを,プライベートクラウド (private cloud) とよぶ. 例えば,大学や研究機関では,その機関の構成員向けの大規模計算機サーバーが運用されていることが多い. プライベートクラウドは,組織の構成員ならば無料もしくは極めて割安のコストで計算を実行できる. しかし,使用できる計算資源の上限は限られる場合が多く,拡張時の柔軟性に欠ける場合もある.

    一方,商用のサービスとして一般の顧客に向けたクラウドのことを,パブリッククラウド (public cloud) とよぶ. 有名なパブリッククラウドプラットフォームの例を挙げると, Google 社が提供する Google Cloud Platform (GCP), Microsoft 社が提供する Azure, Amazon 社が提供する Amazon Web Services (AWS) などがある. パブリッククラウドを利用する場合は,プロバイダーの設定した利用料金を支払うことになる. その分,巨大なデータセンターを運用する企業の計算資源にアクセスすることができるので,計算のキャパシティは無尽蔵にあるといって過言でない.

    第三のクラウドの運用形態として,コミュニティクラウド (community cloud) が挙げられる. これは,例えば政府の省庁・機関など目的・役割を共有する団体・組織が共有して運用するクラウドを指す. 最後に,ハイブリッドクラウド (hybrid cloud) という形態もあり,これはプライベート・パブリック・コミュニティクラウドの二つ以上の組み合わせによって構成されるクラウドのことである. データ保護の観点から,いくつかの機密データやプライバシーに関わる情報はプライベートクラウドに保持し,残りのシステムをパブリッククラウドに依存する,などの形態が想定される.

    本書で説明するのは,基本的にパブリッククラウドを使ったクラウド開発である. 特に,Amazon Web Services (AWS) を使用して,具体的な技術と概念を学んでいく. 一方で,サーバーのスケーリングや仮想計算環境などのテクニックはすべてのクラウドに共通な概念であるので,クラウドのプラットフォームが変わろうと一般に通用する知識も同時に身につくはずだ.

    なぜクラウドを使うのか?

    上述のように,クラウドとはプログラムを通じて自由に計算資源を操作することのできる計算環境である. ここでは,リアルなローカル計算環境と比べて,なぜクラウドを使うと良いことがあるのかについて述べたい.

    1. 自由にサーバーのサイズをスケールできる

      なにか新しいプロジェクトを始めるとき,あらかじめ必要なサーバーのスペックを知るのは難しい. いきなり大きなサーバーを買うのはリスクが高い. 一方で,小さすぎるサーバーでは,後のアップグレードが面倒である. クラウドを利用すれば,プロジェクトを進めながら,必要な分だけの計算資源を確保することができる. 2. 自分でサーバーをメンテナンスする必要がない

      悲しいことに,コンピュータとは古くなるものである.最近の技術の進歩の速度からすると,5 年も経てば,もはや当時の最新コンピュータも化石と同じである. 5 年ごとにサーバーを入れ替えるのは相当な手間である. またサーバーの停電や故障など不意の障害への対応も必要である. クラウドでは,そのようなインフラの整備やメンテナンスはプロバイダーが自動でやってくれるので,ユーザーが心配する必要がない. 3. 初期コスト 0

      自前の計算環境とクラウドの,経済的なコストのイメージを示したのが figure_title である. クラウドを利用する場合の初期コストは基本的に 0 である. その後,使った利用量に応じてコストが増大していく. 一方,自前の計算環境では,大きな初期コストが生じる. その分,初期投資後のコストの増加は,電気利用料やサーバー維持費などに留まるため,クラウドを利用した場合よりも傾きは小さくなる. 自前の計算機では,ある一定期間後,サーバーのアップグレードなどによる支出が生じることがある. 一方,クラウドを利用する場合は,そのような非連続なコストの増大は基本的に生じない. クラウドのコストのカーブが,自前計算環境のコストのカーブの下にある範囲においては,クラウドを使うことは経済的なコスト削減につながる.

      クラウドと自前計算機環境の経済的コストの比較

    とくに,**1.**の点は研究の場面では重要であると筆者は感じる. 研究をやっていて,四六時中計算を走らせ続けるという場合は少ない. むしろ,新しいアルゴリズムが完成したとき・新しいデータが届いたとき,集中的・突発的に計算タスクが増大することが多いだろう. そういったときに,フレキシブルに計算力を増強させることができるのは,クラウドを使う大きなメリットである.

    ここまでクラウドを使うメリットを述べたが,逆に,デメリットというのも当然存在する.

    1. クラウドは賢く使わないといけない

      figure_title で示したコストのカーブにあるとおり,使い方によっては自前の計算環境のほうがコスト的に有利な場面は存在しうる. クラウドを利用する際は,使い終わった計算資源はすぐに削除するなど,利用者が賢く管理を行う必要があり,これを怠ると思いもしない額の請求が届く可能性がある. 2. セキュリティ

      クラウドは,インターネットを通じて世界のどこからでもアクセスできる状態にあり,セキュリティ管理を怠ると簡単にハッキングの対象となりうる. ハッキングを受けると,情報流出だけでなく,経済的な損失を被る可能性がある. 3. ラーニングカーブ

      上記のように,コスト・セキュリティなど,クラウドを利用する際に留意しなければならない点は多い. 賢くクラウドを使うには,十分なクラウドの理解が必要であり,そのラーニングカーブを乗り越える必要がある.

    Mac/Linux などでコマンドを入力するときに使用する,あの黒い画面のことを Terminal とよんだりする. この言葉の語源をご存知だろうか?

    Terminal

    この言葉の語源は,コンピュータが誕生して間もない頃の時代に遡る. その頃のコンピュータというと,何千何万のという数の真空管が接続された,会議室一個分くらいのサイズのマシンであった. そのような高価でメンテが大変な機材であるから,当然みんなでシェアして使うことが前提となる. ユーザーがコンピュータにアクセスするため,マシンからは何本かのケーブルが伸び,それぞれにキーボードとスクリーンが接続されていた… これを Terminal とよんでいたのである. 人々は,代わる代わる Terminal の前に座って,計算機との対話を行っていた.

    時代は流れ,Windows や Mac などのいわゆるパーソナルコンピュータの出現により,コンピュータはみんなで共有するものではなく,個人が所有するものになった.

    最近のクラウドの台頭は,みんなで大きなコンピュータをシェアするという,最初のコンピュータの使われ方に原点回帰していると捉えることもできる. 一方で,スマートフォンやウェアラブルなどのエッジデバイスの普及も盛んであり,個人が複数の"小さな"コンピュータを所有する,という流れも同時に進行しているのである.

    ',33);function m(h,S,T,P,b,v){const e=a;return s(),l("div",null,[_,c(e,{readTime:"4",words:"1.5k"}),f])}const q=n(u,[["render",m]]);export{N as __pageData,q as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,a as t,b as i,c as p}from"./chunks/terminal.94539704.js";import{_ as n,o as s,c as l,H as c,k as o,a as g,Q as d}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"クラウド概論","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/cloud.md","filePath":"development/aws/cloud.md","lastUpdated":1699051935000}'),u={name:"development/aws/cloud.md"},_=o("h1",{id:"クラウド概論",tabindex:"-1"},[g("クラウド概論 "),o("a",{class:"header-anchor",href:"#クラウド概論","aria-label":'Permalink to "クラウド概論"'},"​")],-1),f=d('

    クラウドとは?

    Cloud

    クラウドとはなにか? クラウドという言葉は,それ自身がとても広い意味をもつので,厳密な定義付けを行うことは難しい.

    学術的な意味でのクラウドの定義づけをするとしたら,NIST(米国・国立標準技術研究所) による The NIST Definition of Cloud Computing が引用されることが多い. ここに記載されたクラウドの定義・モデルを図示したのが figure_title である.

    The NIST Definition of Cloud Computing

    これによると,クラウドとは以下の要件が満たされたハードウェア/ソフトウェアの総体のことをいう.

    • On-demand self-service 利用者のリクエストに応じて計算資源が自動的に割り当てられる.

    • Broad network access 利用者はネットワークを通じてクラウドにアクセスできる.

    • Resource pooling クラウドプロバイダーは,所有する計算資源を分割することで複数の利用者に計算資源を割り当てる.

    • Rapid elasticity 利用者のリクエストに応じて,迅速に計算資源の拡大あるいは縮小を行うことができる.

    • Measured service 計算資源の利用量を計測・監視することができる.

    …と,いわれても抽象的でよくわからないかもしれない.もう少し具体的な話をする.

    個人が所有する計算機で, CPU をアップグレードしようと思ったら,物理的に筐体を開け,CPU ソケットを露出させ,新しい CPU に交換する必要があるだろう. あるいは,ストレージがいっぱいになってしまったら,古いディスクを抜き取り,新しいディスクを挿入する必要がある. 計算機の場所を移動させたときには,新しい部屋の LAN ケーブルを差し込まないとネットワークには接続できない.

    クラウドでは,これらの操作がプログラムからのコマンドによって実行できる. CPU が 1000 個欲しいと思ったならば,そのようにクラウドプロバイダーにリクエストを送れば良い. すると,数分もしないうちに 1000 CPU の計算資源が割り当てられる. ストレージを 1TB から 10TB に拡張しようと思ったならば,そのようにコマンドを送ればよい (これは,Google Drive や Dropbox などのサービスなどで馴染みのある人も多いだろう). 計算資源を使い終わったら,そのことをプロバイダーに伝えれば,割り当て分はすぐさま削除される. クラウドプロバイダーは,使った計算資源の量を正確にモニタリングしており,その量をもとに利用料金の計算が行われる.

    このように,クラウドの本質は物理的なハードウェアの仮想化・抽象化であり,利用者はコマンドを通じて,まるでソフトウェアの一部かのように,物理的なハードウェアの管理・運用を行うことができる. もちろん,背後では,データセンターに置かれた膨大な数の計算機が大量の電力を消費しながら稼働している. クラウドプロバイダーはデータセンターの計算資源を上手にやりくりし,ソフトウェアとしてのインターフェースをユーザーに提供することで,このような仮想化・抽象化を達成しているわけである. クラウドプロバイダーの視点からすると,大勢のユーザーに計算機を貸し出し,データセンターの稼働率を常時 100%に近づけることで,利益率の最大化を図っているのである.

    著者の言葉で,クラウドの重要な特性を定義するならば,以下のようになる.

    クラウドとは計算機ハードウェアの抽象化である.つまり,物理的なハードウェアをソフトウェアの一部かのように自在に操作・拡大・接続することを可能にする技術である.

    先述の The NIST Definition of Cloud Computing に戻ると,クラウドプロバイダーによるクラウドサービスの形態としては,次の三つが定義されている (figure_title).

    • Software as a Service (SaaS): クラウド上で実行されるアプリケーションをサービスとして利用者に提供する形態. 例として, Google Drive や Slack などが挙げられる. 利用者は,背後にあるクラウドのインフラ (ネットワークやサーバーなど) には直接触れず,アプリケーションとして提供されているクラウドサービスを享受する.

    • Platform as a Service (PaaS): 顧客の作成したアプリケーション (多くの場合データベースと API リクエスト処理を行うサーバーのコードから構成される) をデプロイする環境をサービスとして利用者に提供する形態. PaaS では利用者はクラウドのインフラに直接触れることはなく,計算負荷が増減した際のサーバーのスケーリングはクラウドプロバイダーによってなされる. 例としては, Google App Engine や Heroku などがある.

    • Infrastructure as a Service (IaaS): クラウド上の計算インフラストラクチャーを従量課金制で利用者に提供する形態. 利用者は必要なネットワーク・サーバー・ストレージをプロバイダーから借り受け,そこに自身のアプリケーションを展開し運用する. IaaS の例としては AWS EC2 などが挙げられる.

    本書が扱うのは,主に IaaS におけるクラウド開発である. すなわち,開発者がクラウドのインフラを直接操作し,所望のネットワーク・サーバー・ストレージなどを一から構成し,そこにアプリケーションを展開するというクラウド開発である. この意味において,クラウドの開発とはクラウドインフラストラクチャーを定義・展開するプログラムを構築するステップインフラ上で実際に走るアプリケーションを作成するステップの二つに分けることができる. この二つは,プログラマーの技術としてはある程度分業を行うことが可能であるが,最も効率化・最適化されたクラウドシステムを構築するためには両方の理解が必須である. 本書では,前者 (クラウドインフラの記述) に重きを置きつつ,アプリケーションレイヤーの話題も取り扱う. PaaS とは,開発者はアプリケーションレイヤーの開発に注力し,クラウドインフラの部分はクラウドプロバイダーに依存するという概念である. PaaS は,クラウドインフラの開発が不要になることで開発の時間が短縮されるが,細かなインフラの挙動はコントロールできないという限界がある. 本書では PaaS についてはとくに取り扱わない.

    SaaS は本書の文脈では開発による"成果物"と捉えられるだろう. すなわち, IaaS を構成するプログラムを作成し展開することによって,一般の人が利用できるようなウェブ上の計算サービスやデータベースを提供することが開発の最終ゴールである. 本書のハンズオンではその実例として,シンプルな SNS の作成 ( (#sec_bashoutter)) などの演習を提供する.

    なお,最近では Function as a Service (FaaS) やサーバーレスコンピューティングなども新たなクラウドのカテゴリとして認知されている. これらの概念については (#sec_intro_serverless) などの章で詳しく触れていく. 本書を読み進める中で明らかになるように,クラウドの技術は日進月歩である. 本書では実用的・教育的な観点から,従来的なクラウドの設計概念に触れたあと,サーバーレスなどの最新の技術も網羅するので,楽しみにしながら読み進めていただきたい.

    最後に,The NIST Definition of Cloud Computing によると,クラウドの運用形態について次のような定義がなされている (figure_title). 特定の組織・団体・企業の内部のみで使用されるクラウドを,プライベートクラウド (private cloud) とよぶ. 例えば,大学や研究機関では,その機関の構成員向けの大規模計算機サーバーが運用されていることが多い. プライベートクラウドは,組織の構成員ならば無料もしくは極めて割安のコストで計算を実行できる. しかし,使用できる計算資源の上限は限られる場合が多く,拡張時の柔軟性に欠ける場合もある.

    一方,商用のサービスとして一般の顧客に向けたクラウドのことを,パブリッククラウド (public cloud) とよぶ. 有名なパブリッククラウドプラットフォームの例を挙げると, Google 社が提供する Google Cloud Platform (GCP), Microsoft 社が提供する Azure, Amazon 社が提供する Amazon Web Services (AWS) などがある. パブリッククラウドを利用する場合は,プロバイダーの設定した利用料金を支払うことになる. その分,巨大なデータセンターを運用する企業の計算資源にアクセスすることができるので,計算のキャパシティは無尽蔵にあるといって過言でない.

    第三のクラウドの運用形態として,コミュニティクラウド (community cloud) が挙げられる. これは,例えば政府の省庁・機関など目的・役割を共有する団体・組織が共有して運用するクラウドを指す. 最後に,ハイブリッドクラウド (hybrid cloud) という形態もあり,これはプライベート・パブリック・コミュニティクラウドの二つ以上の組み合わせによって構成されるクラウドのことである. データ保護の観点から,いくつかの機密データやプライバシーに関わる情報はプライベートクラウドに保持し,残りのシステムをパブリッククラウドに依存する,などの形態が想定される.

    本書で説明するのは,基本的にパブリッククラウドを使ったクラウド開発である. 特に,Amazon Web Services (AWS) を使用して,具体的な技術と概念を学んでいく. 一方で,サーバーのスケーリングや仮想計算環境などのテクニックはすべてのクラウドに共通な概念であるので,クラウドのプラットフォームが変わろうと一般に通用する知識も同時に身につくはずだ.

    なぜクラウドを使うのか?

    上述のように,クラウドとはプログラムを通じて自由に計算資源を操作することのできる計算環境である. ここでは,リアルなローカル計算環境と比べて,なぜクラウドを使うと良いことがあるのかについて述べたい.

    1. 自由にサーバーのサイズをスケールできる

      なにか新しいプロジェクトを始めるとき,あらかじめ必要なサーバーのスペックを知るのは難しい. いきなり大きなサーバーを買うのはリスクが高い. 一方で,小さすぎるサーバーでは,後のアップグレードが面倒である. クラウドを利用すれば,プロジェクトを進めながら,必要な分だけの計算資源を確保することができる. 2. 自分でサーバーをメンテナンスする必要がない

      悲しいことに,コンピュータとは古くなるものである.最近の技術の進歩の速度からすると,5 年も経てば,もはや当時の最新コンピュータも化石と同じである. 5 年ごとにサーバーを入れ替えるのは相当な手間である. またサーバーの停電や故障など不意の障害への対応も必要である. クラウドでは,そのようなインフラの整備やメンテナンスはプロバイダーが自動でやってくれるので,ユーザーが心配する必要がない. 3. 初期コスト 0

      自前の計算環境とクラウドの,経済的なコストのイメージを示したのが figure_title である. クラウドを利用する場合の初期コストは基本的に 0 である. その後,使った利用量に応じてコストが増大していく. 一方,自前の計算環境では,大きな初期コストが生じる. その分,初期投資後のコストの増加は,電気利用料やサーバー維持費などに留まるため,クラウドを利用した場合よりも傾きは小さくなる. 自前の計算機では,ある一定期間後,サーバーのアップグレードなどによる支出が生じることがある. 一方,クラウドを利用する場合は,そのような非連続なコストの増大は基本的に生じない. クラウドのコストのカーブが,自前計算環境のコストのカーブの下にある範囲においては,クラウドを使うことは経済的なコスト削減につながる.

      クラウドと自前計算機環境の経済的コストの比較

    とくに,**1.**の点は研究の場面では重要であると筆者は感じる. 研究をやっていて,四六時中計算を走らせ続けるという場合は少ない. むしろ,新しいアルゴリズムが完成したとき・新しいデータが届いたとき,集中的・突発的に計算タスクが増大することが多いだろう. そういったときに,フレキシブルに計算力を増強させることができるのは,クラウドを使う大きなメリットである.

    ここまでクラウドを使うメリットを述べたが,逆に,デメリットというのも当然存在する.

    1. クラウドは賢く使わないといけない

      figure_title で示したコストのカーブにあるとおり,使い方によっては自前の計算環境のほうがコスト的に有利な場面は存在しうる. クラウドを利用する際は,使い終わった計算資源はすぐに削除するなど,利用者が賢く管理を行う必要があり,これを怠ると思いもしない額の請求が届く可能性がある. 2. セキュリティ

      クラウドは,インターネットを通じて世界のどこからでもアクセスできる状態にあり,セキュリティ管理を怠ると簡単にハッキングの対象となりうる. ハッキングを受けると,情報流出だけでなく,経済的な損失を被る可能性がある. 3. ラーニングカーブ

      上記のように,コスト・セキュリティなど,クラウドを利用する際に留意しなければならない点は多い. 賢くクラウドを使うには,十分なクラウドの理解が必要であり,そのラーニングカーブを乗り越える必要がある.

    Mac/Linux などでコマンドを入力するときに使用する,あの黒い画面のことを Terminal とよんだりする. この言葉の語源をご存知だろうか?

    Terminal

    この言葉の語源は,コンピュータが誕生して間もない頃の時代に遡る. その頃のコンピュータというと,何千何万のという数の真空管が接続された,会議室一個分くらいのサイズのマシンであった. そのような高価でメンテが大変な機材であるから,当然みんなでシェアして使うことが前提となる. ユーザーがコンピュータにアクセスするため,マシンからは何本かのケーブルが伸び,それぞれにキーボードとスクリーンが接続されていた… これを Terminal とよんでいたのである. 人々は,代わる代わる Terminal の前に座って,計算機との対話を行っていた.

    時代は流れ,Windows や Mac などのいわゆるパーソナルコンピュータの出現により,コンピュータはみんなで共有するものではなく,個人が所有するものになった.

    最近のクラウドの台頭は,みんなで大きなコンピュータをシェアするという,最初のコンピュータの使われ方に原点回帰していると捉えることもできる. 一方で,スマートフォンやウェアラブルなどのエッジデバイスの普及も盛んであり,個人が複数の"小さな"コンピュータを所有する,という流れも同時に進行しているのである.

    ',33);function m(h,S,T,P,b,v){const e=a;return s(),l("div",null,[_,c(e,{readTime:"4",words:"1.5k"}),f])}const q=n(u,[["render",m]]);export{N as __pageData,q as default}; diff --git a/assets/development_aws_cloud.md.e679b136.lean.js b/assets/development_aws_cloud.md.148d68f2.lean.js similarity index 92% rename from assets/development_aws_cloud.md.e679b136.lean.js rename to assets/development_aws_cloud.md.148d68f2.lean.js index 455fa8fd..c580d7f0 100644 --- a/assets/development_aws_cloud.md.e679b136.lean.js +++ b/assets/development_aws_cloud.md.148d68f2.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,a as t,b as i,c as p}from"./chunks/terminal.94539704.js";import{_ as n,o as s,c as l,H as c,k as o,a as g,Q as d}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"クラウド概論","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/cloud.md","filePath":"development/aws/cloud.md","lastUpdated":1695377563000}'),u={name:"development/aws/cloud.md"},_=o("h1",{id:"クラウド概論",tabindex:"-1"},[g("クラウド概論 "),o("a",{class:"header-anchor",href:"#クラウド概論","aria-label":'Permalink to "クラウド概論"'},"​")],-1),f=d("",33);function m(h,S,T,P,b,v){const e=a;return s(),l("div",null,[_,c(e,{readTime:"4",words:"1.5k"}),f])}const q=n(u,[["render",m]]);export{N as __pageData,q as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,a as t,b as i,c as p}from"./chunks/terminal.94539704.js";import{_ as n,o as s,c as l,H as c,k as o,a as g,Q as d}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"クラウド概論","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/cloud.md","filePath":"development/aws/cloud.md","lastUpdated":1699051935000}'),u={name:"development/aws/cloud.md"},_=o("h1",{id:"クラウド概論",tabindex:"-1"},[g("クラウド概論 "),o("a",{class:"header-anchor",href:"#クラウド概論","aria-label":'Permalink to "クラウド概論"'},"​")],-1),f=d("",33);function m(h,S,T,P,b,v){const e=a;return s(),l("div",null,[_,c(e,{readTime:"4",words:"1.5k"}),f])}const q=n(u,[["render",m]]);export{N as __pageData,q as default}; diff --git a/assets/development_aws_docker-system.md.4275fd21.lean.js b/assets/development_aws_docker-system.md.4275fd21.lean.js deleted file mode 100644 index 2b0a3f30..00000000 --- a/assets/development_aws_docker-system.md.4275fd21.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,a as o,b as p,c as l,d as r,e as t,f as c,g as i}from"./chunks/ecs.73d77e6a.js";import{_ as y,o as d,c as u,H as m,k as s,a as h,Q as g}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const x=JSON.parse('{"title":"Docker 入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/docker-system.md","filePath":"development/aws/docker-system.md","lastUpdated":1695377563000}'),k={name:"development/aws/docker-system.md"},b=s("h1",{id:"docker-入門",tabindex:"-1"},[h("Docker 入門 "),s("a",{class:"header-anchor",href:"#docker-入門","aria-label":'Permalink to "Docker 入門"'},"​")],-1),A=g("",72);function f(_,D,B,v,C,S){const a=n;return d(),u("div",null,[b,m(a,{readTime:"8",words:"2.2k"}),A])}const E=y(k,[["render",f]]);export{x as __pageData,E as default}; diff --git a/assets/development_aws_docker-system.md.4275fd21.js b/assets/development_aws_docker-system.md.dcee24fc.js similarity index 64% rename from assets/development_aws_docker-system.md.4275fd21.js rename to assets/development_aws_docker-system.md.dcee24fc.js index f99873c9..615d5681 100644 --- a/assets/development_aws_docker-system.md.4275fd21.js +++ b/assets/development_aws_docker-system.md.dcee24fc.js @@ -1,65 +1,65 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,a as o,b as p,c as l,d as r,e as t,f as c,g as i}from"./chunks/ecs.73d77e6a.js";import{_ as y,o as d,c as u,H as m,k as s,a as h,Q as g}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const x=JSON.parse('{"title":"Docker 入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/docker-system.md","filePath":"development/aws/docker-system.md","lastUpdated":1695377563000}'),k={name:"development/aws/docker-system.md"},b=s("h1",{id:"docker-入門",tabindex:"-1"},[h("Docker 入門 "),s("a",{class:"header-anchor",href:"#docker-入門","aria-label":'Permalink to "Docker 入門"'},"​")],-1),A=g('

    ここまでの章で扱ってきたハンズオンでは,単一のサーバーを立ち上げ,それに SSH でログインをして,コマンドを叩くことで計算を行ってきた. いわば,パーソナルコンピュータの延長のような形でクラウドを使ってきたわけである. このような,インターネットのどこからでもアクセスできるパーソナルコンピュータとしてのクラウドという使い方も,もちろん便利であるし,いろいろな応用の可能性がある. しかし,これだけではクラウドの本当の価値は十分に発揮されていないと言うべきだろう. (#chap_cloud_basics) で述べたように,現代的なクラウドの一番の強みは自由に計算機の規模を拡大できることにある. すなわち,多数のサーバーを同時に起動し,複数のジョブを分散並列的に実行させることで大量のデータを処理してこそ,クラウドの本領が発揮されるのである.

    本章からはじまる 3 章分 (Docker 入門, (#sec_fargate_qabot), (#sec_aws_batch)) を使って,クラウドを利用することでどのように大規模な計算システムを構築しビッグデータの解析に立ち向かうのか,その片鱗をお見せしたい. とくに,前章で扱った深層学習をどのようにビッグデータに適用していくかという点に焦点を絞って議論していきたい. そのための前準備として,本章では Docker とよばれる計算機環境の仮想化ソフトウェアを紹介する (figure_title). 現代のクラウドは Docker なしには成り立たないといっても過言ではないだろう. クラウドに限らず,ローカルで行う計算処理にも Docker は大変便利である. AWS からは少し話が離れるが,しっかりと理解して前に進んでもらいたい.

    機械学習の大規模化

    先ほどから"計算システムの大規模化"と繰り返し唱えているが,それは具体的にはどのようなものを指しているのか? ここでは大規模データを処理するための計算機システムを,機械学習を例にとって見てみよう.

    (#sec_scientific_computing) で紹介した GPT-3 のような,超巨大な数のパラメータを有する深層学習モデルを学習させたいとしよう. そのような計算を行いたい場合,一つのサーバーでは計算力が到底足りない. したがって,典型的には figure_title に示すような計算システムの設計がなされる. すなわち,大量の教師データを小さなチャンクとして複数のマシンに分散し,並列的にニューラルネットのパラメータを最適化していくという構造である.

    複数の計算機を使った大規模な深層学習モデルの訓練

    あるいは,学習済みのモデルを大量のデータに適用し,解析を行いたいとしよう. たとえば, SNS のプラットフォームで大量の画像が与えられて,それぞれの写真に何が写っているのかをラベルづけする,などのアプリケーションを想定できる. そのような場合は, figure_title のようなアーキテクチャが考えられるだろう. すなわち,大量のデータを複数のマシンで分割し,それぞれのマシンで推論の計算を行うというような構造である.

    複数の計算機による深層学習モデルを使った推論計算

    このような複数の計算機を同時に走らせるようなアプリケーションをクラウド上で実現するには,どのようにすればよいのだろうか?

    重要なポイントとして, figure_titlefigure_title で起動している複数のマシンは,基本的に全く同一の OS・計算環境を有している点である. ここで,個人のコンピュータで行うようなインストールの操作を,各マシンで行うこともできるが,それは大変な手間であるし,メンテナンスも面倒だろう. すなわち,大規模な計算システムを構築するには,簡単に計算環境を複製できるような仕組みが必要であるということがわかる.

    そのような目的を実現するために使われるのが, Docker とよばれるソフトウェアである.

    Docker とは

    Docker のアイコン

    Docker とは, コンテナ (Container) とよばれる仮想環境下で,ホスト OS とは独立した別の計算環境を走らせるためのソフトウェアである. Docker を使うことで, OS を含めたすべてのプログラムをコンパクトにパッケージングすることが可能になる (パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ). Docker を使うことで,クラウドのサーバー上に瞬時に計算環境を複製することが可能になり, figure_title で見たような複数の計算機を同時に走らせるためのシステムが実現できる.

    Docker は 2013 年に Solomon Hykes らを中心に開発され,それ以降爆発的に普及し,クラウドコンピューティングだけでなく,機械学習・科学計算の文脈などでも欠かすことのできないソフトウェアとなった. Docker はエンタープライズ向けの製品を除き無料で使用することができ,コアの部分は オープンソースプロジェクト として公開されている. Docker は Linux, Windows, Mac いずれの OS でも提供されている. 概念としては, Docker は仮想マシン (Virtual machine; VM) にとても近い. ここでは, VM との対比をしながら,Docker とはなにかを簡単に説明しよう.

    仮想マシン (VM) とは,ホストとなるマシンの上に,仮想化された OS を走らせる技術である (figure_title). VM には ハイパーバイザー (Hypervisor) とよばれるレイヤーが存在する. Hypervisor はまず,物理的な計算機リソース (CPU, RAM, network など) を分割し,仮想化する. たとえば, ホストマシンに物理的な CPU が 4 コアあるとして,ハイパーバイザーはそれを (2,2) 個の組に仮想的に分割することができる. VM 上で起動する OS には,ハイパーバイザーによって仮想化されたハードウェアが割り当てられる. VM 上で起動する OS は基本的に完全に独立であり,たとえば OS-A は OS-B に割り当てられた CPU やメモリー領域にアクセスすることはできない (これを isolation とよぶ). VM を作成するための有名なソフトウェアとしては, VMwareVirtualBoxXen などがある. また,これまで触ってきた EC2 も,基本的に VM 技術を使うことで所望のスペックをもった仮想マシンがユーザーに提示される.

    Docker も, VM と同様に,仮想化された OS をホストの OS 上に走らせるための技術である. VM に対し, Docker ではハードウェアレベルの仮想化は行われておらず,すべての仮想化はソフトウェアレベルで実現されている (figure_title). Docker で走る仮想 OS は,多くの部分をホストの OS に依存しており,結果として非常にコンパクトである. その結果, Docker で仮想 OS を起動するために要する時間は, VM に比べて圧倒的に早い. また, パッケージ化された環境 (=イメージ) のサイズも完全な OS に比べ圧倒的に小さくなるので,ネットワークを通じたやり取りが非常に高速化される点も重要である 加えて, VM のいくつかの実装では,メタル (仮想化マシンに対して,物理的なハードウェア上で直接起動する場合のこと) と比べ,ハイパーバイザーレイヤーでのオーバーヘッドなどにより性能が低下することが知られているが, Docker ではメタルとほぼ同様の性能を引き出すことができるとされている.

    その他, VM との相違点などはたくさんあるのだが,ここではこれ以上詳細には立ち入らない. 大事なのは, Docker とはとてもコンパクトかつハイパフォーマンスな仮想計算環境を作るツールである,という点である. その手軽さゆえに,2013 年の登場以降,クラウドシステムでの利用が急速に増加し,現代のクラウドでは欠くことのできない中心的な技術になっている.

    Docker (左) と VM (右) の比較 (画像出典: https://www.docker.com/blog/containers-replacing-virtual-machines/)

    職業的プログラマーにとっての"三種の神器"とはなんだろうか? 多様な意見があると思うが,筆者は Git, Vim そして Docker を挙げたい.

    Git は多くの読者がご存じの通り,コードの変更を追跡するためのシステムである. Linux の作成者である Linus Torvalds によって 2005 年に誕生した. チームでの開発を進める際には欠かせないツールだ.

    Vim は 1991 年から 30 年以上の間プログラマーたちに愛されてきたテキストエディターである. Stackoverflow が行った 2019 年のアンケート によると,開発環境の部門で 5 位の人気を獲得している. たくさんのショートカットと様々なカスタム設定が提供されているので,初見の人にはなかなかハードルが高いが,一度マスターすれば他のモダンなエディターや統合開発環境に負けない,あるいはそれ以上の開発体験を実現することができる.

    これらの十年以上の歴史あるツールに並んで,第三番目の三種の神器として挙げたいのが Docker だ. Docker はプログラマーの開発のワークフローを一変させた. たとえば,プロジェクトごとに Docker イメージを作成することで,どの OS・コンピュータ でも全く同じ計算環境で開発・テストを実行することができるようになった. また, DevOpsCI / CD (Continuous Integration / Continuous Deployment) といった最近の開発ワークフローも Docker のようなコンテナ技術の存在に立脚している. さらにはサーバーレスコンピューティング ( (#sec_serverless)) といった概念も,コンテナ技術の生んだ大きな技術革新といえる.

    あなたにとっての三種の神器はなんだろうか? また,これからの未来ではどんな新しいツールが三種の神器としてプログラマーのワークフローを革新していくだろうか?

    Docker チュートリアル

    Docker とはなにかを理解するためには,実際に触って動かしてみるのが一番有効な手立てである. ここでは, Docker の簡単なチュートリアルを行っていく.

    Docker のインストールについては, (#sec:install_docker) および 公式のドキュメンテーション を参照してもらいたい. Docker のインストールが完了している前提で,以下は話を進めるものとする.

    Docker 用語集

    Docker を使い始めるに当たり,最初に主要な用語を解説しよう. 次のパラグラフで太字で強調された用語を頭に入れた上で,続くチュートリアルに取り組んでいただきたい.

    Docker を起動する際の大まかなステップを示したのが figure_title である. パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ. イメージは, Docker Hub などのリポジトリで配布されているものをダウンロードするか,自分でカスタムのイメージを作成することも可能である. イメージを作成するための”レシピ”を記述したファイルが Dockerfile である. Dockerfile からイメージを作成する操作を build とよぶ. イメージがホストマシンのメモリにロードされ,起動状態にある計算環境のことを コンテナ (Container) とよぶ. Container を起動するために使用されるコマンドが run である.

    Image と Container

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, (#sec_jupyter_and_deep_learning) でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    sh
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    dockerfile
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,a as o,b as p,c as l,d as r,e as t,f as c,g as i}from"./chunks/ecs.73d77e6a.js";import{_ as y,o as u,c as d,H as m,k as s,a as h,Q as g}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"Docker 入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/docker-system.md","filePath":"development/aws/docker-system.md","lastUpdated":1699051935000}'),b={name:"development/aws/docker-system.md"},k=s("h1",{id:"docker-入門",tabindex:"-1"},[h("Docker 入門 "),s("a",{class:"header-anchor",href:"#docker-入門","aria-label":'Permalink to "Docker 入門"'},"​")],-1),D=g('

    ここまでの章で扱ってきたハンズオンでは,単一のサーバーを立ち上げ,それに SSH でログインをして,コマンドを叩くことで計算を行ってきた. いわば,パーソナルコンピュータの延長のような形でクラウドを使ってきたわけである. このような,インターネットのどこからでもアクセスできるパーソナルコンピュータとしてのクラウドという使い方も,もちろん便利であるし,いろいろな応用の可能性がある. しかし,これだけではクラウドの本当の価値は十分に発揮されていないと言うべきだろう. (#chap_cloud_basics) で述べたように,現代的なクラウドの一番の強みは自由に計算機の規模を拡大できることにある. すなわち,多数のサーバーを同時に起動し,複数のジョブを分散並列的に実行させることで大量のデータを処理してこそ,クラウドの本領が発揮されるのである.

    本章からはじまる 3 章分 (Docker 入門, (#sec_fargate_qabot), (#sec_aws_batch)) を使って,クラウドを利用することでどのように大規模な計算システムを構築しビッグデータの解析に立ち向かうのか,その片鱗をお見せしたい. とくに,前章で扱った深層学習をどのようにビッグデータに適用していくかという点に焦点を絞って議論していきたい. そのための前準備として,本章では Docker とよばれる計算機環境の仮想化ソフトウェアを紹介する (figure_title). 現代のクラウドは Docker なしには成り立たないといっても過言ではないだろう. クラウドに限らず,ローカルで行う計算処理にも Docker は大変便利である. AWS からは少し話が離れるが,しっかりと理解して前に進んでもらいたい.

    機械学習の大規模化

    先ほどから"計算システムの大規模化"と繰り返し唱えているが,それは具体的にはどのようなものを指しているのか? ここでは大規模データを処理するための計算機システムを,機械学習を例にとって見てみよう.

    (#sec_scientific_computing) で紹介した GPT-3 のような,超巨大な数のパラメータを有する深層学習モデルを学習させたいとしよう. そのような計算を行いたい場合,一つのサーバーでは計算力が到底足りない. したがって,典型的には figure_title に示すような計算システムの設計がなされる. すなわち,大量の教師データを小さなチャンクとして複数のマシンに分散し,並列的にニューラルネットのパラメータを最適化していくという構造である.

    複数の計算機を使った大規模な深層学習モデルの訓練

    あるいは,学習済みのモデルを大量のデータに適用し,解析を行いたいとしよう. たとえば, SNS のプラットフォームで大量の画像が与えられて,それぞれの写真に何が写っているのかをラベルづけする,などのアプリケーションを想定できる. そのような場合は, figure_title のようなアーキテクチャが考えられるだろう. すなわち,大量のデータを複数のマシンで分割し,それぞれのマシンで推論の計算を行うというような構造である.

    複数の計算機による深層学習モデルを使った推論計算

    このような複数の計算機を同時に走らせるようなアプリケーションをクラウド上で実現するには,どのようにすればよいのだろうか?

    重要なポイントとして, figure_titlefigure_title で起動している複数のマシンは,基本的に全く同一の OS・計算環境を有している点である. ここで,個人のコンピュータで行うようなインストールの操作を,各マシンで行うこともできるが,それは大変な手間であるし,メンテナンスも面倒だろう. すなわち,大規模な計算システムを構築するには,簡単に計算環境を複製できるような仕組みが必要であるということがわかる.

    そのような目的を実現するために使われるのが, Docker とよばれるソフトウェアである.

    Docker とは

    Docker のアイコン

    Docker とは, コンテナ (Container) とよばれる仮想環境下で,ホスト OS とは独立した別の計算環境を走らせるためのソフトウェアである. Docker を使うことで, OS を含めたすべてのプログラムをコンパクトにパッケージングすることが可能になる (パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ). Docker を使うことで,クラウドのサーバー上に瞬時に計算環境を複製することが可能になり, figure_title で見たような複数の計算機を同時に走らせるためのシステムが実現できる.

    Docker は 2013 年に Solomon Hykes らを中心に開発され,それ以降爆発的に普及し,クラウドコンピューティングだけでなく,機械学習・科学計算の文脈などでも欠かすことのできないソフトウェアとなった. Docker はエンタープライズ向けの製品を除き無料で使用することができ,コアの部分は オープンソースプロジェクト として公開されている. Docker は Linux, Windows, Mac いずれの OS でも提供されている. 概念としては, Docker は仮想マシン (Virtual machine; VM) にとても近い. ここでは, VM との対比をしながら,Docker とはなにかを簡単に説明しよう.

    仮想マシン (VM) とは,ホストとなるマシンの上に,仮想化された OS を走らせる技術である (figure_title). VM には ハイパーバイザー (Hypervisor) とよばれるレイヤーが存在する. Hypervisor はまず,物理的な計算機リソース (CPU, RAM, network など) を分割し,仮想化する. たとえば, ホストマシンに物理的な CPU が 4 コアあるとして,ハイパーバイザーはそれを (2,2) 個の組に仮想的に分割することができる. VM 上で起動する OS には,ハイパーバイザーによって仮想化されたハードウェアが割り当てられる. VM 上で起動する OS は基本的に完全に独立であり,たとえば OS-A は OS-B に割り当てられた CPU やメモリー領域にアクセスすることはできない (これを isolation とよぶ). VM を作成するための有名なソフトウェアとしては, VMwareVirtualBoxXen などがある. また,これまで触ってきた EC2 も,基本的に VM 技術を使うことで所望のスペックをもった仮想マシンがユーザーに提示される.

    Docker も, VM と同様に,仮想化された OS をホストの OS 上に走らせるための技術である. VM に対し, Docker ではハードウェアレベルの仮想化は行われておらず,すべての仮想化はソフトウェアレベルで実現されている (figure_title). Docker で走る仮想 OS は,多くの部分をホストの OS に依存しており,結果として非常にコンパクトである. その結果, Docker で仮想 OS を起動するために要する時間は, VM に比べて圧倒的に早い. また, パッケージ化された環境 (=イメージ) のサイズも完全な OS に比べ圧倒的に小さくなるので,ネットワークを通じたやり取りが非常に高速化される点も重要である 加えて, VM のいくつかの実装では,メタル (仮想化マシンに対して,物理的なハードウェア上で直接起動する場合のこと) と比べ,ハイパーバイザーレイヤーでのオーバーヘッドなどにより性能が低下することが知られているが, Docker ではメタルとほぼ同様の性能を引き出すことができるとされている.

    その他, VM との相違点などはたくさんあるのだが,ここではこれ以上詳細には立ち入らない. 大事なのは, Docker とはとてもコンパクトかつハイパフォーマンスな仮想計算環境を作るツールである,という点である. その手軽さゆえに,2013 年の登場以降,クラウドシステムでの利用が急速に増加し,現代のクラウドでは欠くことのできない中心的な技術になっている.

    Docker (左) と VM (右) の比較 (画像出典: https://www.docker.com/blog/containers-replacing-virtual-machines/)

    職業的プログラマーにとっての"三種の神器"とはなんだろうか? 多様な意見があると思うが,筆者は Git, Vim そして Docker を挙げたい.

    Git は多くの読者がご存じの通り,コードの変更を追跡するためのシステムである. Linux の作成者である Linus Torvalds によって 2005 年に誕生した. チームでの開発を進める際には欠かせないツールだ.

    Vim は 1991 年から 30 年以上の間プログラマーたちに愛されてきたテキストエディターである. Stackoverflow が行った 2019 年のアンケート によると,開発環境の部門で 5 位の人気を獲得している. たくさんのショートカットと様々なカスタム設定が提供されているので,初見の人にはなかなかハードルが高いが,一度マスターすれば他のモダンなエディターや統合開発環境に負けない,あるいはそれ以上の開発体験を実現することができる.

    これらの十年以上の歴史あるツールに並んで,第三番目の三種の神器として挙げたいのが Docker だ. Docker はプログラマーの開発のワークフローを一変させた. たとえば,プロジェクトごとに Docker イメージを作成することで,どの OS・コンピュータ でも全く同じ計算環境で開発・テストを実行することができるようになった. また, DevOpsCI / CD (Continuous Integration / Continuous Deployment) といった最近の開発ワークフローも Docker のようなコンテナ技術の存在に立脚している. さらにはサーバーレスコンピューティング ( (#sec_serverless)) といった概念も,コンテナ技術の生んだ大きな技術革新といえる.

    あなたにとっての三種の神器はなんだろうか? また,これからの未来ではどんな新しいツールが三種の神器としてプログラマーのワークフローを革新していくだろうか?

    Docker チュートリアル

    Docker とはなにかを理解するためには,実際に触って動かしてみるのが一番有効な手立てである. ここでは, Docker の簡単なチュートリアルを行っていく.

    Docker のインストールについては, (#sec:install_docker) および 公式のドキュメンテーション を参照してもらいたい. Docker のインストールが完了している前提で,以下は話を進めるものとする.

    Docker 用語集

    Docker を使い始めるに当たり,最初に主要な用語を解説しよう. 次のパラグラフで太字で強調された用語を頭に入れた上で,続くチュートリアルに取り組んでいただきたい.

    Docker を起動する際の大まかなステップを示したのが figure_title である. パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ. イメージは, Docker Hub などのリポジトリで配布されているものをダウンロードするか,自分でカスタムのイメージを作成することも可能である. イメージを作成するための”レシピ”を記述したファイルが Dockerfile である. Dockerfile からイメージを作成する操作を build とよぶ. イメージがホストマシンのメモリにロードされ,起動状態にある計算環境のことを コンテナ (Container) とよぶ. Container を起動するために使用されるコマンドが run である.

    Image と Container

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, (#sec_jupyter_and_deep_learning) でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    sh
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    dockerfile
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \\
    -    && apt-get install nano
    +RUN apt-get update \\
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \\
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \\
    -    && tar -xzf Python-3.7.6.tgz \\
    -    && cd Python-3.7.6 \\
    -    && ./configure --enable-optimizations \\
    -    && make install
    +#
    +RUN cd /opt \\
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \\
    +    && tar -xzf Python-3.7.6.tgz \\
    +    && cd Python-3.7.6 \\
    +    && ./configure --enable-optimizations \\
    +    && make install
     
    -RUN cd /opt \\
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \\
    -    && unzip awscliv2.zip \\
    -    && ./aws/install
    +RUN cd /opt \\
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \\
    +    && unzip awscliv2.zip \\
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +# copy hands-on source code in /root/
    +COPY handson/ /root/handson
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \\
    -    && apt-get install nano
    +RUN apt-get update \\
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \\
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \\
    -    && tar -xzf Python-3.7.6.tgz \\
    -    && cd Python-3.7.6 \\
    -    && ./configure --enable-optimizations \\
    -    && make install
    +#
    +RUN cd /opt \\
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \\
    +    && tar -xzf Python-3.7.6.tgz \\
    +    && cd Python-3.7.6 \\
    +    && ./configure --enable-optimizations \\
    +    && make install
     
    -RUN cd /opt \\
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \\
    -    && unzip awscliv2.zip \\
    -    && ./aws/install
    +RUN cd /opt \\
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \\
    +    && unzip awscliv2.zip \\
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    Singularity は科学計算や HPC (High Performance Computing) の分野で人気の高いコンテナプラットフォームである. Singularity では大学・研究機関の HPC クラスターでの運用に適したような設計が施されている. たとえば, Docker は基本的には root 権限で実行されるのに対し, Singularity はユーザー権限 (コマンドを実行したユーザー自身) でプログラムが実行される. root 権限での実行は Web サーバーのように個人・企業がある特定のサービスのために運用するサーバーでは問題ないが,多数のユーザーが多様な目的で計算を実行する HPC クラスターでは問題となる. また,Singularity は独自のイメージの作成方法・エコシステムをもっているが, Docker イメージを Singularity のイメージに変換し実行する機能も有している.

    podman は Red Hat 社によって開発されたもう一つのコンテナプラットフォームである. podman は基本的に Docker と同一のコマンドを採用しているが,実装は Red Hat によってスクラッチから行われた. podman では, Singularity と同様にユーザー権限でのプログラムの実行を可能であり,クラウドおよび HPC の両方の環境に対応するコンテナプラットフォームを目指して作られた. また,その名前にあるとおり pod とよばれる独自の概念が導入されている.

    著者の個人的な意見としては,現時点では Docker をマスターしておけば当面は困ることはないと考えるが,興味のある読者はぜひこれらのツールも試してみてはいかがだろうか?

    Elastic Container Service (ECS)

    ECS のアイコン

    ここまでに説明してきたように, Docker を使うことで仮想計算環境を簡単に複製・起動することが可能になる. 本章の最後の話題として, AWS 上で Docker を使った計算システムを構築する方法を解説しよう.

    Elastic Container Service (ECS) とは, Docker を使った計算機クラスターを AWS 上に作成するためのツールである (figure_title). ECS を使用することで, Docker にパッケージされたアプリケーションを計算機クラスターに投入したり,計算機クラスターのインスタンスを追加・削除する操作 (=スケーリング) を行うことができる.

    ECS の概要を示したのが figure_title である. ECS は,タスク (Task) と呼ばれる単位で管理された計算ジョブを受け付ける. システムにタスクが投入されると,ECS は最初にタスクで指定された Docker イメージを外部レジストリからダウンロードしてくる. 外部レジストリとしては, Docker Hub や AWS 独自の Docker レジストリである ECR (Elastic Container Registry) を指定することができる.

    ECS の次の重要な役割はタスクの配置である. あらかじめ定義されたクラスター内で,計算負荷が小さい仮想インスタンスを選び出し,そこに Docker イメージを配置することで指定された計算タスクが開始される. "計算負荷が小さい仮想インスタンスを選び出す" と言ったが,具体的にどのような戦略・ポリシーでこの選択を行うかは,ユーザーの指定したパラメータに従う.

    また,クラスターのスケーリングも ECS における重要な概念である. スケーリングとは,クラスター内のインスタンスの計算負荷をモニタリングし,計算負荷に応じてインスタンスの起動・停止を行う操作を指す. クラスター全体の計算負荷が指定された閾値 (たとえば 80%の稼働率) を超えていた場合,新たな仮想インスタンスをクラスター内に立ち上げる操作を scale-out (スケールアウト) とよび, 負荷が減った場合に不要なインスタンスを停止する操作を scale-in (スケールイン) とよぶ. クラスターのスケーリングは, ECS がほかの AWS のサービスと連携することで実現される. 具体的には, EC2 の Auto scaling group (ASG)Fargate の2つの選択肢が多くの場合選択される. ASG については (#sec_aws_batch), Fargate については (#sec_fargate_qabot) でより詳細に解説する.

    これら一連のタスクの管理を, ECS は自動でやってくれる. クラスターのスケーリングやタスクの配置に関してのパラメータを一度指定してしまえば,ユーザーは (ほとんどなにも考えずに) 大量のタスクを投入することができる. クラスターのスケーリングによってタスクの量にちょうど十分なだけのインスタンスが起動し,タスクが完了した後は不要なインスタンスはすべて停止される.

    さて,ここまで説明的な話が続いてしまったが,次章からは早速 Docker と AWS を使って大規模な並列計算システムを構築していこう!

    ECS の概要

    ',72);function f(_,D,B,v,C,S){const a=n;return d(),u("div",null,[b,m(a,{readTime:"8",words:"2.2k"}),A])}const E=y(k,[["render",f]]);export{x as __pageData,E as default}; +# copy hands-on source code in /root/ +COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    Singularity は科学計算や HPC (High Performance Computing) の分野で人気の高いコンテナプラットフォームである. Singularity では大学・研究機関の HPC クラスターでの運用に適したような設計が施されている. たとえば, Docker は基本的には root 権限で実行されるのに対し, Singularity はユーザー権限 (コマンドを実行したユーザー自身) でプログラムが実行される. root 権限での実行は Web サーバーのように個人・企業がある特定のサービスのために運用するサーバーでは問題ないが,多数のユーザーが多様な目的で計算を実行する HPC クラスターでは問題となる. また,Singularity は独自のイメージの作成方法・エコシステムをもっているが, Docker イメージを Singularity のイメージに変換し実行する機能も有している.

    podman は Red Hat 社によって開発されたもう一つのコンテナプラットフォームである. podman は基本的に Docker と同一のコマンドを採用しているが,実装は Red Hat によってスクラッチから行われた. podman では, Singularity と同様にユーザー権限でのプログラムの実行を可能であり,クラウドおよび HPC の両方の環境に対応するコンテナプラットフォームを目指して作られた. また,その名前にあるとおり pod とよばれる独自の概念が導入されている.

    著者の個人的な意見としては,現時点では Docker をマスターしておけば当面は困ることはないと考えるが,興味のある読者はぜひこれらのツールも試してみてはいかがだろうか?

    Elastic Container Service (ECS)

    ECS のアイコン

    ここまでに説明してきたように, Docker を使うことで仮想計算環境を簡単に複製・起動することが可能になる. 本章の最後の話題として, AWS 上で Docker を使った計算システムを構築する方法を解説しよう.

    Elastic Container Service (ECS) とは, Docker を使った計算機クラスターを AWS 上に作成するためのツールである (figure_title). ECS を使用することで, Docker にパッケージされたアプリケーションを計算機クラスターに投入したり,計算機クラスターのインスタンスを追加・削除する操作 (=スケーリング) を行うことができる.

    ECS の概要を示したのが figure_title である. ECS は,タスク (Task) と呼ばれる単位で管理された計算ジョブを受け付ける. システムにタスクが投入されると,ECS は最初にタスクで指定された Docker イメージを外部レジストリからダウンロードしてくる. 外部レジストリとしては, Docker Hub や AWS 独自の Docker レジストリである ECR (Elastic Container Registry) を指定することができる.

    ECS の次の重要な役割はタスクの配置である. あらかじめ定義されたクラスター内で,計算負荷が小さい仮想インスタンスを選び出し,そこに Docker イメージを配置することで指定された計算タスクが開始される. "計算負荷が小さい仮想インスタンスを選び出す" と言ったが,具体的にどのような戦略・ポリシーでこの選択を行うかは,ユーザーの指定したパラメータに従う.

    また,クラスターのスケーリングも ECS における重要な概念である. スケーリングとは,クラスター内のインスタンスの計算負荷をモニタリングし,計算負荷に応じてインスタンスの起動・停止を行う操作を指す. クラスター全体の計算負荷が指定された閾値 (たとえば 80%の稼働率) を超えていた場合,新たな仮想インスタンスをクラスター内に立ち上げる操作を scale-out (スケールアウト) とよび, 負荷が減った場合に不要なインスタンスを停止する操作を scale-in (スケールイン) とよぶ. クラスターのスケーリングは, ECS がほかの AWS のサービスと連携することで実現される. 具体的には, EC2 の Auto scaling group (ASG)Fargate の2つの選択肢が多くの場合選択される. ASG については (#sec_aws_batch), Fargate については (#sec_fargate_qabot) でより詳細に解説する.

    これら一連のタスクの管理を, ECS は自動でやってくれる. クラスターのスケーリングやタスクの配置に関してのパラメータを一度指定してしまえば,ユーザーは (ほとんどなにも考えずに) 大量のタスクを投入することができる. クラスターのスケーリングによってタスクの量にちょうど十分なだけのインスタンスが起動し,タスクが完了した後は不要なインスタンスはすべて停止される.

    さて,ここまで説明的な話が続いてしまったが,次章からは早速 Docker と AWS を使って大規模な並列計算システムを構築していこう!

    ECS の概要

    ',72);function C(A,_,F,f,v,E){const a=n;return u(),d("div",null,[k,m(a,{readTime:"8",words:"2.2k"}),D])}const x=y(b,[["render",C]]);export{P as __pageData,x as default}; diff --git a/assets/development_aws_docker-system.md.dcee24fc.lean.js b/assets/development_aws_docker-system.md.dcee24fc.lean.js new file mode 100644 index 00000000..f9debbb0 --- /dev/null +++ b/assets/development_aws_docker-system.md.dcee24fc.lean.js @@ -0,0 +1 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,a as o,b as p,c as l,d as r,e as t,f as c,g as i}from"./chunks/ecs.73d77e6a.js";import{_ as y,o as u,c as d,H as m,k as s,a as h,Q as g}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"Docker 入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/docker-system.md","filePath":"development/aws/docker-system.md","lastUpdated":1699051935000}'),b={name:"development/aws/docker-system.md"},k=s("h1",{id:"docker-入門",tabindex:"-1"},[h("Docker 入門 "),s("a",{class:"header-anchor",href:"#docker-入門","aria-label":'Permalink to "Docker 入門"'},"​")],-1),D=g("",72);function C(A,_,F,f,v,E){const a=n;return u(),d("div",null,[k,m(a,{readTime:"8",words:"2.2k"}),D])}const x=y(b,[["render",C]]);export{P as __pageData,x as default}; diff --git a/assets/development_aws_handson-bashoutter.md.890a8ec8.js b/assets/development_aws_handson-bashoutter.md.890a8ec8.js new file mode 100644 index 00000000..2eb784bd --- /dev/null +++ b/assets/development_aws_handson-bashoutter.md.890a8ec8.js @@ -0,0 +1,409 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as c,f as r,g as i,h as y}from"./chunks/bashoutter_2.cd8a2a95.js";import{_ as d,o as u,c as A,H as b,k as s,a as m,Q as D}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const I=JSON.parse('{"title":"Hands-on #6: Bashoutter","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-bashoutter.md","filePath":"development/aws/handson-bashoutter.md","lastUpdated":1699051935000}'),C={name:"development/aws/handson-bashoutter.md"},h=s("h1",{id:"hands-on-6-bashoutter",tabindex:"-1"},[m("Hands-on #6: Bashoutter "),s("a",{class:"header-anchor",href:"#hands-on-6-bashoutter","aria-label":'Permalink to "Hands-on \\#6: Bashoutter"'},"​")],-1),F=D('

    さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

    ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

    準備

    ハンズオンのソースコードは GitHub の handson/bashoutter に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. それ以外に必要な準備はない.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行できる.

    アプリケーションの説明

    API

    今回のアプリケーションでは,人々からの俳句の投稿を受け付けたり,投稿された俳句の一覧を取得する,といった機能を実装したい. この機能を実現するための最小限の設計として, table_title に示すような四つの REST API を今回は実装する. 俳句を投稿する,閲覧する,削除するという基本的なデータ操作を行うための API が完備されている. また, PATCH /haiku/{item_id} は, {item_id} で指定された俳句に”いいね”をするために使用する.

    Bashoutter API

    GET /haiku

    俳句の一覧を取得する

    POST /haiku

    新しい俳句を投稿する

    PATCH /haiku/{item_id}

    {item_id} で指定された俳句にお気に入り票を一つ入れる

    DELETE /haiku/{item_id}

    {item_id} で指定された俳句を削除する

    それぞれの API のパラメータおよび返り値の詳細は,ハンズオンのソースコードの中の swagger.yml に定義してある.

    Open API Specification (OAS; 少し前は Swagger Specification とよばれていた) は, REST API のための記述フォーマットである. OAS に従って API の仕様が記述されていると,簡単にドキュメンテーションを生成したり,クライアントアプリケーションを自動生成することができる. 今回用意した API 仕様 も, OAS に従って書いてある. 詳しくは Swagger の公式ドキュメンテーション などを参照.

    アプリケーションアーキテクチャ

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#5で作製するアプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントからの API リクエストは, API Gateway (後述)にまず送信され, API の URI で指定された Lambda 関数へ転送される.

    • それぞれの API のパス (リソース) ごとに独立した Lambda を用意する.

    • 俳句の情報 (作者,本文,投稿日時など) を記録するためのデータベース (DynamoDB) を用意する.

    • 各 Lambda 関数には, DynamoDB へのアクセス権を付与する.

    • 最後に,ウェブブラウザからコンテンツを表示できるよう, ウェブページの静的コンテンツを配信するための S3 バケットを用意する.クライアントはこの S3 バケットにアクセスすることで HTML/CSS/JS などのコンテンツを取得する.

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    python
    class Bashoutter(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
    +
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
    +
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
    +
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
    +
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
    +
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    class Bashoutter(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
    +
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
    +
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
    +
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
    +
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
    +
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

    • 静的コンテンツを配信するための S3 バケットを用意している.

    • それぞれの API で実行される Lambda 関数を定義している. 関数は Python3.7 で書かれており,コードは handson/bashoutter/api/api.py にある.

    • <3> で定義された Lambda 関数に対し,データベースへの読み書きのアクセス権限を付与している.

    • ここで,API Gateway により,各 API パスとそこで実行されるべき Lambda 関数を紐付けている.

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    python
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    今回のハンズオンでは説明の簡略化のため CloudFront の設定を行わなかったが,興味のある読者は次のリンクのプログラムが参考になるだろう.

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    python
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    python
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
    +
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
    +
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
    +
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
    +
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    python
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は (#sec_aws_batch) で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    そのような理由により,このコードでは GET のハンドラー関数に対しては grant_read_data() によって, read 権限のみを付与している.

    API Gateway

    API Gateway とは, API の"入り口"として,API のリクエストパスに従って Lambda や EC2 などに接続を行うという機能を担う (figure_title). Lambda や EC2 によって行われた処理の結果は,再び API Gateway を経由してクライアントに返される. このように,クライアントとバックエンドサーバーの間に立ち, API のリソースパスに応じて接続先を振り分けるようなサーバーをルーター,あるいはリバースプロキシとよんだりする. 従来的には,ルーターにはそれ専用の仮想サーバーが置かれることが一般的であった. しかし, API Gateway はサーバーレスなルーターとして,固定されたサーバーを配置することなく, API のリクエストが来たときのみ起動し,API のルーティングを実行する. サーバーレスであることの当然の帰結として,アクセスの件数が増大したときにはそれにルーティングの処理能力を自動で増やす機能も備わっている.

    API Gateway

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    python
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
    +
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
    +
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
    +
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
    +
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

    • 次に, api.root.add_resource() のメソッドを呼ぶことで, /haiku という API パスを追加している.

    • 続いて, add_method() を呼ぶことで, GET, POST のメソッドを /haiku のパスに定義している.

    • さらに, haiku.add_resource("{item_id}") により, /haiku/{item_id} という API パスを追加している.

    • 最後に, add_method() を呼ぶことにより, PATCH, DELETE のメソッドを /haiku/{item_id} のパスに定義している.

    このように, API Gateway の使い方は非常にシンプルで,逐次的に API パスとそこで実行されるメソッド・Lambda を記述していくだけでよい.

    このプログラムで 新規 API を作成すると, ランダムな URL がその API のエンドポイントとして割り当てられる. これを. api.example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    API Gateway コンソール画面 (1)

    今回デプロイした "BashoutterApi" という名前の API をクリックすることで figure_title のような画面に遷移し,詳細情報を閲覧できる. GET /haiku, POST /haiku などが定義されていることが確認できる.

    それぞれのメソッドをクリックすると,そのメソッドの詳細情報を確認できる. API Gateway は,前述したルーティングの機能だけでなく,認証機能などを追加することも可能である. このハンズオンではとくにこれらの機能は使用しないが, "Method Request" と書いてある項目などがそれに相当する. 次に, figure_title で画面右端の赤色で囲った部分に,この API で呼ばれる Lambda 関数が指定されていることに注目しよう. 関数名をクリックと,該当する Lambda のコンソールに遷移し,関数の中身を閲覧することが可能である.

    API Gateway コンソール画面 (2)

    次に, S3 のコンソール画面に移ってみよう. bashouter- で始まるランダムな名前のバケットが見つかるはずである (figure_title).

    S3 コンソール画面

    バケットの名前をクリックすることで,バケットの中身を確認してみよう. index.html のほか, css/, js/ などのディレクトリがあるのが確認できるだろう (figure_title). これらが,ウェブページの"枠"を定義している静的コンテンツである.

    S3 バケットの中身

    API リクエストを送信する

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    $ http GET "\${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    sh
    $ http POST "\${ENDPOINT_URL}/haiku" \\
    +username="松尾芭蕉" \\
    +first="閑さや" \\
    +second="岩にしみ入る" \\
    +third="蝉の声"
    $ http POST "\${ENDPOINT_URL}/haiku" \\
    +username="松尾芭蕉" \\
    +first="閑さや" \\
    +second="岩にしみ入る" \\
    +third="蝉の声"

    次のような出力が得られるだろう.

    sh
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    +
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]
    $ http GET "\${ENDPOINT_URL}/haiku"
    +
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    sh
    $ http PATCH "\${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "\${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]
    $ http GET "\${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    sh
    $ http DELETE "\${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "\${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている ( (#fig:web_server) 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    ウェブブラウザを開き,アドレスバーに S3 の URL を入力しへアクセスしてみよう. すると, figure_title のようなページが表示されるはずである.

    "Bashoutter" の GUI 画面

    ページが表示されたら,一番上の "API Endpoint URL" と書いてあるテキストボックスに,今回デプロイした API Gateway の URL を入力する (今回のアプリケーションでは,API Gateway の URL はランダムに割り当てられるのでこのような GUI の仕様になっている). そうしたら,画面の "REFRESH" と書いてあるボタンを押してみよう. データベースに俳句が登録済みであれば,俳句の一覧が表示されるはずである. 各俳句の左下にあるハートのアイコンをクリックすることで, "like" の票を入れることができる.

    新しい俳句を投稿するには,五七五と投稿者の名前を入力して, "POST" を押す. "POST" を押した後は,再び "REFRESH" ボタンを押すことで最新の俳句のリストをデータベースから取得する.

    アプリケーションの削除

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. (#sec_intro_serverless) では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    これらの演習を通じて,世の中のウェブサービスがどのようにしてでき上がっているのか,少し理解が深まっただろうか? また,そのようなウェブアプリケーションを自分が作りたいと思ったとき,今回のハンズオンがその出発点となることができたならば幸いである.

    ',126);function E(_,B,g,q,k,v){const a=n;return u(),A("div",null,[h,b(a,{readTime:"12",words:"2.9k"}),F])}const S=d(C,[["render",E]]);export{I as __pageData,S as default}; diff --git a/assets/development_aws_handson-bashoutter.md.d59bc53b.lean.js b/assets/development_aws_handson-bashoutter.md.890a8ec8.lean.js similarity index 50% rename from assets/development_aws_handson-bashoutter.md.d59bc53b.lean.js rename to assets/development_aws_handson-bashoutter.md.890a8ec8.lean.js index f0ed53d3..112a64eb 100644 --- a/assets/development_aws_handson-bashoutter.md.d59bc53b.lean.js +++ b/assets/development_aws_handson-bashoutter.md.890a8ec8.lean.js @@ -1 +1 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as o,c as e,d as t,e as c,f as r,g as i,h as y}from"./chunks/bashoutter_2.cd8a2a95.js";import{_ as d,o as u,c as b,H as A,k as s,a as m,Q as B}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Hands-on #6: Bashoutter","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-bashoutter.md","filePath":"development/aws/handson-bashoutter.md","lastUpdated":1695377563000}'),h={name:"development/aws/handson-bashoutter.md"},_=s("h1",{id:"hands-on-6-bashoutter",tabindex:"-1"},[m("Hands-on #6: Bashoutter "),s("a",{class:"header-anchor",href:"#hands-on-6-bashoutter","aria-label":'Permalink to "Hands-on \\#6: Bashoutter"'},"​")],-1),q=B("",126);function g(k,v,f,D,C,P){const a=n;return u(),b("div",null,[_,A(a,{readTime:"12",words:"2.9k"}),q])}const L=d(h,[["render",g]]);export{S as __pageData,L as default}; +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as c,f as r,g as i,h as y}from"./chunks/bashoutter_2.cd8a2a95.js";import{_ as d,o as u,c as A,H as b,k as s,a as m,Q as D}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const I=JSON.parse('{"title":"Hands-on #6: Bashoutter","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-bashoutter.md","filePath":"development/aws/handson-bashoutter.md","lastUpdated":1699051935000}'),C={name:"development/aws/handson-bashoutter.md"},h=s("h1",{id:"hands-on-6-bashoutter",tabindex:"-1"},[m("Hands-on #6: Bashoutter "),s("a",{class:"header-anchor",href:"#hands-on-6-bashoutter","aria-label":'Permalink to "Hands-on \\#6: Bashoutter"'},"​")],-1),F=D("",126);function E(_,B,g,q,k,v){const a=n;return u(),A("div",null,[h,b(a,{readTime:"12",words:"2.9k"}),F])}const S=d(C,[["render",E]]);export{I as __pageData,S as default}; diff --git a/assets/development_aws_handson-bashoutter.md.d59bc53b.js b/assets/development_aws_handson-bashoutter.md.d59bc53b.js deleted file mode 100644 index 2a446245..00000000 --- a/assets/development_aws_handson-bashoutter.md.d59bc53b.js +++ /dev/null @@ -1,409 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as o,c as e,d as t,e as c,f as r,g as i,h as y}from"./chunks/bashoutter_2.cd8a2a95.js";import{_ as d,o as u,c as b,H as A,k as s,a as m,Q as B}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Hands-on #6: Bashoutter","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-bashoutter.md","filePath":"development/aws/handson-bashoutter.md","lastUpdated":1695377563000}'),h={name:"development/aws/handson-bashoutter.md"},_=s("h1",{id:"hands-on-6-bashoutter",tabindex:"-1"},[m("Hands-on #6: Bashoutter "),s("a",{class:"header-anchor",href:"#hands-on-6-bashoutter","aria-label":'Permalink to "Hands-on \\#6: Bashoutter"'},"​")],-1),q=B('

    さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

    ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

    準備

    ハンズオンのソースコードは GitHub の handson/bashoutter に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. それ以外に必要な準備はない.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行できる.

    アプリケーションの説明

    API

    今回のアプリケーションでは,人々からの俳句の投稿を受け付けたり,投稿された俳句の一覧を取得する,といった機能を実装したい. この機能を実現するための最小限の設計として, table_title に示すような四つの REST API を今回は実装する. 俳句を投稿する,閲覧する,削除するという基本的なデータ操作を行うための API が完備されている. また, PATCH /haiku/{item_id} は, {item_id} で指定された俳句に”いいね”をするために使用する.

    Bashoutter API

    GET /haiku

    俳句の一覧を取得する

    POST /haiku

    新しい俳句を投稿する

    PATCH /haiku/{item_id}

    {item_id} で指定された俳句にお気に入り票を一つ入れる

    DELETE /haiku/{item_id}

    {item_id} で指定された俳句を削除する

    それぞれの API のパラメータおよび返り値の詳細は,ハンズオンのソースコードの中の swagger.yml に定義してある.

    Open API Specification (OAS; 少し前は Swagger Specification とよばれていた) は, REST API のための記述フォーマットである. OAS に従って API の仕様が記述されていると,簡単にドキュメンテーションを生成したり,クライアントアプリケーションを自動生成することができる. 今回用意した API 仕様 も, OAS に従って書いてある. 詳しくは Swagger の公式ドキュメンテーション などを参照.

    アプリケーションアーキテクチャ

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#5で作製するアプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントからの API リクエストは, API Gateway (後述)にまず送信され, API の URI で指定された Lambda 関数へ転送される.

    • それぞれの API のパス (リソース) ごとに独立した Lambda を用意する.

    • 俳句の情報 (作者,本文,投稿日時など) を記録するためのデータベース (DynamoDB) を用意する.

    • 各 Lambda 関数には, DynamoDB へのアクセス権を付与する.

    • 最後に,ウェブブラウザからコンテンツを表示できるよう, ウェブページの静的コンテンツを配信するための S3 バケットを用意する.クライアントはこの S3 バケットにアクセスすることで HTML/CSS/JS などのコンテンツを取得する.

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    python
    class Bashoutter(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    -
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    -
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    -
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    -
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    -
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    class Bashoutter(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    -
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    -
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    -
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    -
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    -
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

    • 静的コンテンツを配信するための S3 バケットを用意している.

    • それぞれの API で実行される Lambda 関数を定義している. 関数は Python3.7 で書かれており,コードは handson/bashoutter/api/api.py にある.

    • <3> で定義された Lambda 関数に対し,データベースへの読み書きのアクセス権限を付与している.

    • ここで,API Gateway により,各 API パスとそこで実行されるべき Lambda 関数を紐付けている.

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    python
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    今回のハンズオンでは説明の簡略化のため CloudFront の設定を行わなかったが,興味のある読者は次のリンクのプログラムが参考になるだろう.

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    python
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    python
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    -
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    -
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    -
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    -
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    python
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は (#sec_aws_batch) で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    そのような理由により,このコードでは GET のハンドラー関数に対しては grant_read_data() によって, read 権限のみを付与している.

    API Gateway

    API Gateway とは, API の"入り口"として,API のリクエストパスに従って Lambda や EC2 などに接続を行うという機能を担う (figure_title). Lambda や EC2 によって行われた処理の結果は,再び API Gateway を経由してクライアントに返される. このように,クライアントとバックエンドサーバーの間に立ち, API のリソースパスに応じて接続先を振り分けるようなサーバーをルーター,あるいはリバースプロキシとよんだりする. 従来的には,ルーターにはそれ専用の仮想サーバーが置かれることが一般的であった. しかし, API Gateway はサーバーレスなルーターとして,固定されたサーバーを配置することなく, API のリクエストが来たときのみ起動し,API のルーティングを実行する. サーバーレスであることの当然の帰結として,アクセスの件数が増大したときにはそれにルーティングの処理能力を自動で増やす機能も備わっている.

    API Gateway

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    python
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    -
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    -
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    -
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    -
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

    • 次に, api.root.add_resource() のメソッドを呼ぶことで, /haiku という API パスを追加している.

    • 続いて, add_method() を呼ぶことで, GET, POST のメソッドを /haiku のパスに定義している.

    • さらに, haiku.add_resource("{item_id}") により, /haiku/{item_id} という API パスを追加している.

    • 最後に, add_method() を呼ぶことにより, PATCH, DELETE のメソッドを /haiku/{item_id} のパスに定義している.

    このように, API Gateway の使い方は非常にシンプルで,逐次的に API パスとそこで実行されるメソッド・Lambda を記述していくだけでよい.

    このプログラムで 新規 API を作成すると, ランダムな URL がその API のエンドポイントとして割り当てられる. これを. api.example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    API Gateway コンソール画面 (1)

    今回デプロイした "BashoutterApi" という名前の API をクリックすることで figure_title のような画面に遷移し,詳細情報を閲覧できる. GET /haiku, POST /haiku などが定義されていることが確認できる.

    それぞれのメソッドをクリックすると,そのメソッドの詳細情報を確認できる. API Gateway は,前述したルーティングの機能だけでなく,認証機能などを追加することも可能である. このハンズオンではとくにこれらの機能は使用しないが, "Method Request" と書いてある項目などがそれに相当する. 次に, figure_title で画面右端の赤色で囲った部分に,この API で呼ばれる Lambda 関数が指定されていることに注目しよう. 関数名をクリックと,該当する Lambda のコンソールに遷移し,関数の中身を閲覧することが可能である.

    API Gateway コンソール画面 (2)

    次に, S3 のコンソール画面に移ってみよう. bashouter- で始まるランダムな名前のバケットが見つかるはずである (figure_title).

    S3 コンソール画面

    バケットの名前をクリックすることで,バケットの中身を確認してみよう. index.html のほか, css/, js/ などのディレクトリがあるのが確認できるだろう (figure_title). これらが,ウェブページの"枠"を定義している静的コンテンツである.

    S3 バケットの中身

    API リクエストを送信する

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    $ http GET "\${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    sh
    $ http POST "\${ENDPOINT_URL}/haiku" \\
    -username="松尾芭蕉" \\
    -first="閑さや" \\
    -second="岩にしみ入る" \\
    -third="蝉の声"
    $ http POST "\${ENDPOINT_URL}/haiku" \\
    -username="松尾芭蕉" \\
    -first="閑さや" \\
    -second="岩にしみ入る" \\
    -third="蝉の声"

    次のような出力が得られるだろう.

    sh
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    -
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    $ http GET "\${ENDPOINT_URL}/haiku"
    -
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    sh
    $ http PATCH "\${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "\${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    $ http GET "\${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    sh
    $ http DELETE "\${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "\${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている ( (#fig:web_server) 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    ウェブブラウザを開き,アドレスバーに S3 の URL を入力しへアクセスしてみよう. すると, figure_title のようなページが表示されるはずである.

    "Bashoutter" の GUI 画面

    ページが表示されたら,一番上の "API Endpoint URL" と書いてあるテキストボックスに,今回デプロイした API Gateway の URL を入力する (今回のアプリケーションでは,API Gateway の URL はランダムに割り当てられるのでこのような GUI の仕様になっている). そうしたら,画面の "REFRESH" と書いてあるボタンを押してみよう. データベースに俳句が登録済みであれば,俳句の一覧が表示されるはずである. 各俳句の左下にあるハートのアイコンをクリックすることで, "like" の票を入れることができる.

    新しい俳句を投稿するには,五七五と投稿者の名前を入力して, "POST" を押す. "POST" を押した後は,再び "REFRESH" ボタンを押すことで最新の俳句のリストをデータベースから取得する.

    アプリケーションの削除

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. (#sec_intro_serverless) では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    これらの演習を通じて,世の中のウェブサービスがどのようにしてでき上がっているのか,少し理解が深まっただろうか? また,そのようなウェブアプリケーションを自分が作りたいと思ったとき,今回のハンズオンがその出発点となることができたならば幸いである.

    ',126);function g(k,v,f,D,C,P){const a=n;return u(),b("div",null,[_,A(a,{readTime:"12",words:"2.9k"}),q])}const L=d(h,[["render",g]]);export{S as __pageData,L as default}; diff --git a/assets/development_aws_handson-ec2.md.2a763e5b.js b/assets/development_aws_handson-ec2.md.2a763e5b.js deleted file mode 100644 index 75defb84..00000000 --- a/assets/development_aws_handson-ec2.md.2a763e5b.js +++ /dev/null @@ -1,193 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as c,f as r}from"./chunks/ec2_keypair_console.fc89ef69.js";import{a as y,_ as i}from"./chunks/VPC.e1acca4d.js";import{_ as d,o as A,c as u,H as B,k as s,a as b,Q as m}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const H=JSON.parse('{"title":"Hands-on #1: 初めての EC2 インスタンスを起動する","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-ec2.md","filePath":"development/aws/handson-ec2.md","lastUpdated":1695377563000}'),h={name:"development/aws/handson-ec2.md"},g=s("h1",{id:"hands-on-1-初めての-ec2-インスタンスを起動する",tabindex:"-1"},[b("Hands-on #1: 初めての EC2 インスタンスを起動する "),s("a",{class:"header-anchor",href:"#hands-on-1-初めての-ec2-インスタンスを起動する","aria-label":'Permalink to "Hands-on \\#1: 初めての EC2 インスタンスを起動する"'},"​")],-1),D=m('

    ハンズオンの第一回では, CDK を使って EC2 のインスタンス(仮想サーバー)を作成し,SSH でサーバーにログインする,という演習を行う. このハンズオンを終えれば,あなたは自分だけのサーバーを AWS 上に立ち上げ,自由に計算を走らせることができるようになるのである!

    準備

    ハンズオンのソースコードは GitHub の handson/ec2-get-started に置いてある.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行することができる.

    まずは,ハンズオンを実行するための環境を整える. これらの環境整備は,後のハンズオンでも前提となるものなので確実にミスなく行っていただきたい.

    • AWS Account: ハンズオンを実行するには個人の AWS アカウントが必要である. AWS アカウントの取得については (#sec:create_aws_account) を参照のこと.

    • Python と Node.js: 本ハンズオンを実行するには,Python (3.6 以上),Node.js (12.0 以上) がインストールされていなければならない.

    • AWS CLI: AWS CLI のインストールについては, (#aws_cli_install) を参照. ここに記載されている認証鍵の設定も済ませておくこと.

    • AWS CDK: AWS CDK のインストールについては, (#aws_cdk_install) を参照.

    • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.

    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    使用方法については (#sec_handson_docker) を参照のこと.

    SSH

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する ( (#environments) を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    python
    class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    • まず最初に,VPC を定義する.

    • 次に, security group (SG) を定義している. ここでは,任意の IPv4 のアドレスからの,ポート 22 (SSH の接続に使用される)への接続を許可している. それ以外の接続は拒絶される.

    • 最後に,上記で作った VPC と SG が付与された EC2 インスタンスを作成している. インスタンスタイプは t2.micro を選択し, Amazon Linux を OS として設定している.

    それぞれについて,もう少し詳しく説明しよう.

    VPC (Virtual Private Cloud)

    VPC のアイコン.

    VPC

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    python
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

    • cidr="10.10.0.0/23" : このパラメータは,VPC 内の IPv4 のレンジを指定している. CIDR 記法については, Wikipediaなどを参照. 10.10.0.0/2310.10.0.0 から 10.10.1.255 までの 512 個の連続したアドレス範囲を指している. つまり,この VPC では最大で 512 個のユニークな IPv4 アドレスが使えることになる. 今回はサーバーは一つなので 512 個は明らかに多すぎるが,VPC はアドレスの数はどれだけ作成しても無料なので,多めに作成した.

    • subnet_configuration=... : このパラメータは,VPC にどのようなサブネットを作るか,を決めている. サブネットの種類には private subnetpublic subnet の二種類がある. private subnet は基本的にインターネットとは遮断されたサブネット環境である. インターネットと繋がっていないので,セキュリティは極めて高く, VPC 内のサーバーとのみ通信を行えばよい EC2 インスタンスはここに配置する. Public subnet とはインターネットに繋がったサブネットである. 本ハンズオンで作成するサーバーは,外から SSH でログインを行いたいので, Public subnet 内に配置する. より詳細な記述は 公式ドキュメンテーション を参照.

    • natgateways=0 : これは少し高度な内容なので省略する (興味のある読者は 公式ドキュメンテーションを参照). が,これを 0 にしておかないと,NAT Gateway の利用料金が発生してしまうので,注意!

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    python
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    EC2 (Elastic Compute Cloud)

    EC2 のアイコン.

    EC2

    EC2 は AWS 上に仮想サーバーを立ち上げるサービスである. 個々の起動状態にある仮想サーバーのことをインスタンス (instance) とよぶ (しかし,口語的なコミュニケーションにおいては,サーバーとインスタンスという言葉は相互互換的に用いられることが多い).

    EC2 では用途に応じて様々なインスタンスタイプが提供されている. table_title に,代表的なインスタンスタイプの例を挙げる (執筆時点での情報). EC2 のインスタンスタイプのすべてのリストは 公式ドキュメンテーション "Amazon EC2 Instance Types" で見ることができる.

    EC2 instance types

    InstancevCPUMemory (GiB)Network bandwidth (Gbps)Price per hour ($)
    t2.micro11-0.0116
    t2.small12-0.023
    t2.medium24-0.0464
    c5.24xlarge96192254.08
    c5n.18xlarge721921003.888
    x1e.16xlarge6419521013.344

    table_title からわかるように, CPU は 1 コアから 96 コアまで,メモリーは 1GB から 2TB 以上まで,ネットワーク帯域は最大で 100Gbps まで,幅広く選択することができる. また,時間あたりの料金は,CPU・メモリーの占有数にほぼ比例する形で増加する. EC2 はサーバーの起動時間を秒単位で記録しており,利用料金は使用時間に比例する形で決定される. 例えば, t2.medium のインスタンスを 10 時間起動した場合,0.0464 * 10 = 0.464 ドルの料金が発生する.

    AWS には 無料利用枠 というものがあり, t2.micro であれば月に 750 時間までは無料で利用することができる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    python
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, (#sec_jupyter_and_deep_learning) でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    さて,ハンズオンのコードの理解ができたところで,プログラムを実際に実行してみよう.繰り返しになるが, 準備 での準備ができていることが前提である.

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    sh
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は (#venv_quick_guide) に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    AWS のシークレットキーをセットする

    AWS CLI および AWS CDK を使うには, AWS のシークレットキーが設定されている必要がある. シークレットキーの発行については (#aws_secrets) を参照のこと. シークレットキーを発行したら, (#aws_cli_install) を参照し,コマンドラインの設定を行う.

    手順をここに短く要約すると,一つ目の方法は AWS_ACCESS_KEY_ID などの環境変数を設定するやり方である. もう一つの方法は, ~/.aws/credentials に認証情報を保存しておく方式である. シークレットキーの設定は AWS CLI/CDK を使用するうえで共通のステップになるので,しっかりと理解しておくように.

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    sh
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    sh
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    おめでとう!これで,めでたく AWS 上に EC2 仮想サーバーを起動し,リモートからアクセスできるようになった!

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    sh
    $ cat /proc/cpuinfo
    -
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    $ cat /proc/cpuinfo
    -
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    bash
    $  top -n 1
    -
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    -
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    -
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    -
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    sh
    $ sudo yum update -y
    -$ sudo yum install -y python36
    $ sudo yum update -y
    -$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    sh
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    EC2 コンソール画面

    コンソール右上で,正しいリージョン (今回の場合は ap-northeast-1, Tokyo) が選択されているか,注意する!

    前章で CloudFormation について触れたが,今回デプロイしたアプリケーションも,CloudFormation のスタックとして管理されている. スタック (stack) とは, AWS リソースの集合のことを指す. 今回の場合は, VPC/EC2/SG などがスタックの中に含まれている. コンソールで CloudFormation のページに行ってみよう (figure_title).

    CloudFormation コンソール画面

    "MyFirstEc2" という名前のスタックがあることが確認できる. クリックをして中身を見てみると,EC2, VPC などのリソースがこのスタックに紐付いていることがわかる.

    スタックを削除

    これにて,第一回のハンズオンで説明すべき事柄はすべて完了した. 最後に,使わなくなったスタックを削除しよう. スタックの削除には,二つの方法がある.

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    ここまでが,本書の第一部の内容である. 盛りだくさんの内容であったが,ついてこれたであろうか?

    (#chap_cloud_basics) では,クラウドの定義と用語の説明を行ったあと,なぜクラウドを使うのか,という点を議論した. 続いて (#sec_aws_general_introduction) では,クラウドを学ぶ具体的なプラットフォームとして AWS を取り上げ, AWS を使用するにあたり最低限必要な知識と用語の説明を行った. さらに, Hands-on #1: 初めての EC2 インスタンスを起動する のハンズオンでは AWS CLI と AWS CDK を使って,自身のプライベートなサーバーを AWS 上に立ち上げる演習を行った.

    これらを通じて,いかに簡単に (たった数行のコマンドで!) 仮想サーバーを立ち上げたり,削除したりすることができるか,体験できただろう. 筆者は, (#chap_cloud_basics) でクラウドの最も重要な側面はダイナミックに計算リソースを拡大・縮小できることである,と述べた. この言葉の意味が,ハンズオンを通じてより明らかになっただろうか? ここで学んだ技術を少し応用するだけで,自分のウェブページをホストする仮想サーバーを作成したり,大量のコアを搭載した EC2 インスタンスを用意して科学計算を実行するなど,いろいろなアプリケーションが実現できる.

    次章からは,今回学んだクラウドの技術を基に,より現実に即した問題を解くことを体験してもらう. お楽しみに!

    ',134);function v(_,C,k,S,f,q){const a=n;return A(),u("div",null,[g,B(a,{readTime:"11",words:"2.6k"}),D])}const $=d(h,[["render",v]]);export{H as __pageData,$ as default}; diff --git a/assets/development_aws_handson-ec2.md.43188290.js b/assets/development_aws_handson-ec2.md.43188290.js new file mode 100644 index 00000000..2c50bd90 --- /dev/null +++ b/assets/development_aws_handson-ec2.md.43188290.js @@ -0,0 +1,193 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as c,f as r}from"./chunks/ec2_keypair_console.fc89ef69.js";import{a as y,_ as i}from"./chunks/VPC.e1acca4d.js";import{_ as F,o as C,c as A,H as d,k as s,a as D,Q as u}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const H=JSON.parse('{"title":"Hands-on #1: 初めての EC2 インスタンスを起動する","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-ec2.md","filePath":"development/aws/handson-ec2.md","lastUpdated":1699051935000}'),b={name:"development/aws/handson-ec2.md"},m=s("h1",{id:"hands-on-1-初めての-ec2-インスタンスを起動する",tabindex:"-1"},[D("Hands-on #1: 初めての EC2 インスタンスを起動する "),s("a",{class:"header-anchor",href:"#hands-on-1-初めての-ec2-インスタンスを起動する","aria-label":'Permalink to "Hands-on \\#1: 初めての EC2 インスタンスを起動する"'},"​")],-1),E=u('

    ハンズオンの第一回では, CDK を使って EC2 のインスタンス(仮想サーバー)を作成し,SSH でサーバーにログインする,という演習を行う. このハンズオンを終えれば,あなたは自分だけのサーバーを AWS 上に立ち上げ,自由に計算を走らせることができるようになるのである!

    準備

    ハンズオンのソースコードは GitHub の handson/ec2-get-started に置いてある.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行することができる.

    まずは,ハンズオンを実行するための環境を整える. これらの環境整備は,後のハンズオンでも前提となるものなので確実にミスなく行っていただきたい.

    • AWS Account: ハンズオンを実行するには個人の AWS アカウントが必要である. AWS アカウントの取得については (#sec:create_aws_account) を参照のこと.

    • Python と Node.js: 本ハンズオンを実行するには,Python (3.6 以上),Node.js (12.0 以上) がインストールされていなければならない.

    • AWS CLI: AWS CLI のインストールについては, (#aws_cli_install) を参照. ここに記載されている認証鍵の設定も済ませておくこと.

    • AWS CDK: AWS CDK のインストールについては, (#aws_cdk_install) を参照.

    • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.

    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    使用方法については (#sec_handson_docker) を参照のこと.

    SSH

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する ( (#environments) を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    python
    class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    • まず最初に,VPC を定義する.

    • 次に, security group (SG) を定義している. ここでは,任意の IPv4 のアドレスからの,ポート 22 (SSH の接続に使用される)への接続を許可している. それ以外の接続は拒絶される.

    • 最後に,上記で作った VPC と SG が付与された EC2 インスタンスを作成している. インスタンスタイプは t2.micro を選択し, Amazon Linux を OS として設定している.

    それぞれについて,もう少し詳しく説明しよう.

    VPC (Virtual Private Cloud)

    VPC のアイコン.

    VPC

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    python
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

    • cidr="10.10.0.0/23" : このパラメータは,VPC 内の IPv4 のレンジを指定している. CIDR 記法については, Wikipediaなどを参照. 10.10.0.0/2310.10.0.0 から 10.10.1.255 までの 512 個の連続したアドレス範囲を指している. つまり,この VPC では最大で 512 個のユニークな IPv4 アドレスが使えることになる. 今回はサーバーは一つなので 512 個は明らかに多すぎるが,VPC はアドレスの数はどれだけ作成しても無料なので,多めに作成した.

    • subnet_configuration=... : このパラメータは,VPC にどのようなサブネットを作るか,を決めている. サブネットの種類には private subnetpublic subnet の二種類がある. private subnet は基本的にインターネットとは遮断されたサブネット環境である. インターネットと繋がっていないので,セキュリティは極めて高く, VPC 内のサーバーとのみ通信を行えばよい EC2 インスタンスはここに配置する. Public subnet とはインターネットに繋がったサブネットである. 本ハンズオンで作成するサーバーは,外から SSH でログインを行いたいので, Public subnet 内に配置する. より詳細な記述は 公式ドキュメンテーション を参照.

    • natgateways=0 : これは少し高度な内容なので省略する (興味のある読者は 公式ドキュメンテーションを参照). が,これを 0 にしておかないと,NAT Gateway の利用料金が発生してしまうので,注意!

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    python
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    EC2 (Elastic Compute Cloud)

    EC2 のアイコン.

    EC2

    EC2 は AWS 上に仮想サーバーを立ち上げるサービスである. 個々の起動状態にある仮想サーバーのことをインスタンス (instance) とよぶ (しかし,口語的なコミュニケーションにおいては,サーバーとインスタンスという言葉は相互互換的に用いられることが多い).

    EC2 では用途に応じて様々なインスタンスタイプが提供されている. table_title に,代表的なインスタンスタイプの例を挙げる (執筆時点での情報). EC2 のインスタンスタイプのすべてのリストは 公式ドキュメンテーション "Amazon EC2 Instance Types" で見ることができる.

    EC2 instance types

    InstancevCPUMemory (GiB)Network bandwidth (Gbps)Price per hour ($)
    t2.micro11-0.0116
    t2.small12-0.023
    t2.medium24-0.0464
    c5.24xlarge96192254.08
    c5n.18xlarge721921003.888
    x1e.16xlarge6419521013.344

    table_title からわかるように, CPU は 1 コアから 96 コアまで,メモリーは 1GB から 2TB 以上まで,ネットワーク帯域は最大で 100Gbps まで,幅広く選択することができる. また,時間あたりの料金は,CPU・メモリーの占有数にほぼ比例する形で増加する. EC2 はサーバーの起動時間を秒単位で記録しており,利用料金は使用時間に比例する形で決定される. 例えば, t2.medium のインスタンスを 10 時間起動した場合,0.0464 * 10 = 0.464 ドルの料金が発生する.

    AWS には 無料利用枠 というものがあり, t2.micro であれば月に 750 時間までは無料で利用することができる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    python
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, (#sec_jupyter_and_deep_learning) でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    さて,ハンズオンのコードの理解ができたところで,プログラムを実際に実行してみよう.繰り返しになるが, 準備 での準備ができていることが前提である.

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    sh
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は (#venv_quick_guide) に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    AWS のシークレットキーをセットする

    AWS CLI および AWS CDK を使うには, AWS のシークレットキーが設定されている必要がある. シークレットキーの発行については (#aws_secrets) を参照のこと. シークレットキーを発行したら, (#aws_cli_install) を参照し,コマンドラインの設定を行う.

    手順をここに短く要約すると,一つ目の方法は AWS_ACCESS_KEY_ID などの環境変数を設定するやり方である. もう一つの方法は, ~/.aws/credentials に認証情報を保存しておく方式である. シークレットキーの設定は AWS CLI/CDK を使用するうえで共通のステップになるので,しっかりと理解しておくように.

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    sh
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    sh
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    おめでとう!これで,めでたく AWS 上に EC2 仮想サーバーを起動し,リモートからアクセスできるようになった!

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    sh
    $ cat /proc/cpuinfo
    +
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB
    $ cat /proc/cpuinfo
    +
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    bash
    $  top -n 1
    +
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
    +
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    +
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
    +
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    sh
    $ sudo yum update -y
    +$ sudo yum install -y python36
    $ sudo yum update -y
    +$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    sh
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    EC2 コンソール画面

    コンソール右上で,正しいリージョン (今回の場合は ap-northeast-1, Tokyo) が選択されているか,注意する!

    前章で CloudFormation について触れたが,今回デプロイしたアプリケーションも,CloudFormation のスタックとして管理されている. スタック (stack) とは, AWS リソースの集合のことを指す. 今回の場合は, VPC/EC2/SG などがスタックの中に含まれている. コンソールで CloudFormation のページに行ってみよう (figure_title).

    CloudFormation コンソール画面

    "MyFirstEc2" という名前のスタックがあることが確認できる. クリックをして中身を見てみると,EC2, VPC などのリソースがこのスタックに紐付いていることがわかる.

    スタックを削除

    これにて,第一回のハンズオンで説明すべき事柄はすべて完了した. 最後に,使わなくなったスタックを削除しよう. スタックの削除には,二つの方法がある.

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    ここまでが,本書の第一部の内容である. 盛りだくさんの内容であったが,ついてこれたであろうか?

    (#chap_cloud_basics) では,クラウドの定義と用語の説明を行ったあと,なぜクラウドを使うのか,という点を議論した. 続いて (#sec_aws_general_introduction) では,クラウドを学ぶ具体的なプラットフォームとして AWS を取り上げ, AWS を使用するにあたり最低限必要な知識と用語の説明を行った. さらに, Hands-on #1: 初めての EC2 インスタンスを起動する のハンズオンでは AWS CLI と AWS CDK を使って,自身のプライベートなサーバーを AWS 上に立ち上げる演習を行った.

    これらを通じて,いかに簡単に (たった数行のコマンドで!) 仮想サーバーを立ち上げたり,削除したりすることができるか,体験できただろう. 筆者は, (#chap_cloud_basics) でクラウドの最も重要な側面はダイナミックに計算リソースを拡大・縮小できることである,と述べた. この言葉の意味が,ハンズオンを通じてより明らかになっただろうか? ここで学んだ技術を少し応用するだけで,自分のウェブページをホストする仮想サーバーを作成したり,大量のコアを搭載した EC2 インスタンスを用意して科学計算を実行するなど,いろいろなアプリケーションが実現できる.

    次章からは,今回学んだクラウドの技術を基に,より現実に即した問題を解くことを体験してもらう. お楽しみに!

    ',134);function h(B,g,v,_,k,S){const a=n;return C(),A("div",null,[m,d(a,{readTime:"11",words:"2.6k"}),E])}const $=F(b,[["render",h]]);export{H as __pageData,$ as default}; diff --git a/assets/development_aws_handson-ec2.md.2a763e5b.lean.js b/assets/development_aws_handson-ec2.md.43188290.lean.js similarity index 58% rename from assets/development_aws_handson-ec2.md.2a763e5b.lean.js rename to assets/development_aws_handson-ec2.md.43188290.lean.js index 13867458..6ca92d55 100644 --- a/assets/development_aws_handson-ec2.md.2a763e5b.lean.js +++ b/assets/development_aws_handson-ec2.md.43188290.lean.js @@ -1 +1 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as c,f as r}from"./chunks/ec2_keypair_console.fc89ef69.js";import{a as y,_ as i}from"./chunks/VPC.e1acca4d.js";import{_ as d,o as A,c as u,H as B,k as s,a as b,Q as m}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const H=JSON.parse('{"title":"Hands-on #1: 初めての EC2 インスタンスを起動する","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-ec2.md","filePath":"development/aws/handson-ec2.md","lastUpdated":1695377563000}'),h={name:"development/aws/handson-ec2.md"},g=s("h1",{id:"hands-on-1-初めての-ec2-インスタンスを起動する",tabindex:"-1"},[b("Hands-on #1: 初めての EC2 インスタンスを起動する "),s("a",{class:"header-anchor",href:"#hands-on-1-初めての-ec2-インスタンスを起動する","aria-label":'Permalink to "Hands-on \\#1: 初めての EC2 インスタンスを起動する"'},"​")],-1),D=m("",134);function v(_,C,k,S,f,q){const a=n;return A(),u("div",null,[g,B(a,{readTime:"11",words:"2.6k"}),D])}const $=d(h,[["render",v]]);export{H as __pageData,$ as default}; +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as c,f as r}from"./chunks/ec2_keypair_console.fc89ef69.js";import{a as y,_ as i}from"./chunks/VPC.e1acca4d.js";import{_ as F,o as C,c as A,H as d,k as s,a as D,Q as u}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const H=JSON.parse('{"title":"Hands-on #1: 初めての EC2 インスタンスを起動する","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-ec2.md","filePath":"development/aws/handson-ec2.md","lastUpdated":1699051935000}'),b={name:"development/aws/handson-ec2.md"},m=s("h1",{id:"hands-on-1-初めての-ec2-インスタンスを起動する",tabindex:"-1"},[D("Hands-on #1: 初めての EC2 インスタンスを起動する "),s("a",{class:"header-anchor",href:"#hands-on-1-初めての-ec2-インスタンスを起動する","aria-label":'Permalink to "Hands-on \\#1: 初めての EC2 インスタンスを起動する"'},"​")],-1),E=u("",134);function h(B,g,v,_,k,S){const a=n;return C(),A("div",null,[m,d(a,{readTime:"11",words:"2.6k"}),E])}const $=F(b,[["render",h]]);export{H as __pageData,$ as default}; diff --git a/assets/development_aws_handson-jupyter.md.7f479319.js b/assets/development_aws_handson-jupyter.md.7f479319.js deleted file mode 100644 index 397f2830..00000000 --- a/assets/development_aws_handson-jupyter.md.7f479319.js +++ /dev/null @@ -1,247 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as r,f as c,g as y,h as i,i as d,j as u,k as m,l as h,m as b,n as B,o as A,p as g}from"./chunks/mnist_prediction.4ba5b405.js";import{_,o as v,c as f,H as k,k as s,a as D,Q as q}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Hands-on #2: AWS でディープラーニングを実践","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-jupyter.md","filePath":"development/aws/handson-jupyter.md","lastUpdated":1695377563000}'),C={name:"development/aws/handson-jupyter.md"},S=s("h1",{id:"hands-on-2-aws-でディープラーニングを実践",tabindex:"-1"},[D("Hands-on #2: AWS でディープラーニングを実践 "),s("a",{class:"header-anchor",href:"#hands-on-2-aws-でディープラーニングを実践","aria-label":'Permalink to "Hands-on \\#2: AWS でディープラーニングを実践"'},"​")],-1),z=q('

    準備

    ハンズオン第二回では, GPU を搭載した EC2 インスタンスを起動し,深層学習モデルの学習と推論を実行する演習を行う.

    ハンズオンのソースコードは GitHub の handson/mnist に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. それ以外に必要な準備はない.

    初期状態の AWS アカウントでは, GPU 搭載の G タイプのインスタンスの起動上限が 0 になっていることがある. これを確認するには, AWS コンソールから EC2 の画面を開き,左のメニューから Limits を選択する. その中の Running On-Demand All G instances という数字が G インスタンスの起動上限を表している.

    もし,これが 0 になっていた場合は, AWS の自動申請フォームから上限緩和のリクエストを送る必要がある. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,東京 (ap-northeast-1) リージョンでは 0.71 $/hour のコストが発生する.

    AWS Educate Starter Account を使用している読者へ: 執筆時点においては, Starter Account には GPU 搭載型インスタンスを起動できないという制限が設けられている. したがって, Starter Account のユーザーはこのハンズオンを実行することはできない. 興味のある読者は,制限のない一般アカウントを自分自身で取得する必要があることに注意.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#2で作製するアプリケーションのアーキテクチャ

    図の多くの部分が,第一回ハンズオンで作成したアプリケーションと共通していることに気がつくだろう. 少しの変更で,簡単にディープラーニングを走らせる環境を構築することができるのである!主な変更点は次の3点である.

    • GPU を搭載した g4dn.xlarge インスタンスタイプを使用

    • ディープラーニングに使うプログラムがあらかじめインストールされた DLAMI (後述) を使用

    • SSH にポートフォワーディングのオプションつけてサーバーに接続し,サーバーで起動している Jupyter Notebook (後述) を使ってプログラムを書いたり実行したりする

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    python
    class Ec2ForDl(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class Ec2ForDl(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, (#sec_scientific_computing) ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

    • ここでは,Deep Learning 用の諸々のソフトウェアがプリンストールされた AMI (Deep Learning Amazon Machine Image; DLAMI) を選択している (第一回では,Amazon Linux という AMI を使用していた). 使用する AMI の ID は リージョンごとに指定する必要があり,ここでは us-east-1ap-northeast-1 でそれぞれ定義している.

    DLAMI という新しい概念が出てきたので,説明しよう.

    AMI が us-east-1ap-northeast-1 でしか定義されていないので,提供されているコードはこの二つのリージョンのみでデプロイ可能である. もしほかのリージョンを利用したい場合は, AMI の ID を自身で検索し,コードに書き込む必要がある.

    DLAMI (Deep Learning Amazon Machine Image)

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    最も low-level なレイヤーとしては, GPU ドライバー がインストールされている. GPU ドライバーなしには OS は GPU とコマンドのやり取りをすることができない. 次のレイヤーが CUDAcuDNN である. CUDA は, NVIDIA 社が開発した, GPU 上で汎用コンピューティングを行うための言語であり, C++ 言語を拡張したシンタックスを備える. cuDNN は CUDA で書かれたディープラーニングのライブラリであり,n 次元の畳み込みなどの演算が実装されている. ここまでが, "Base" とよばれるタイプの DLAMI の中身である.

    これに加えて, "Conda" とよばれるタイプには, "Base" のプログラム基盤の上に, TensorFlowPyTorch などのライブラリがインストールされている. さらに, Anaconda による仮想環境を使うことによって, TensorFlow の環境・ PyTorch の環境・ MxNet の環境など,フレームワークを簡単に切り替えることができる (これについては,後のハンズオンで触れる). また, Jupyter Notebook もインストール済みである.

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    -
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    -
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    SSH ログインコマンドの <IP address> 部分は自身のインスタンスの IP アドレスを代入することを忘れずに.

    本書の提供している Docker を使ってデプロイを実行した人へ

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    Jupyter Notebook とは,インタラクティブに Python のプログラムを書いたり実行したりするためのツールである. Jupyter は GUI としてウェブブラウザを介してアクセスする形式をとっており,まるでノートを書くように,プロットやテーブルのデータも美しく表示することができる (figure_title). Python に慣れている読者は,きっと一度は使ったことがあるだろう.

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    sh
    $ cd ~ # go to home directory
    -$ jupyter notebook
    $ cd ~ # go to home directory
    -$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    Jupyter Notebook の使い方 (超簡易版)

    • Shift + Enter: セルを実行

    • Esc: Command mode に遷移

    • メニューバーの "+" ボタン または Command mode で A ⇒ セルを追加

    • メニューバーの "ハサミ" ボタン または Command mode で X ⇒ セルを削除

    ショートカットの一覧などは Ventsislav Yordanov 氏によるブログ が参考になる.

    PyTorch はじめの一歩

    PyTorch は Facebook AI Research LAB (FAIR) が中心となって開発を進めている,オープンソースのディープラーニングのライブラリである. PyTorch は 有名な例で言えば Tesla 社の自動運転プロジェクトなどで使用されており,執筆時点において最も人気の高いディープラーニングライブラリの一つである. 本ハンズオンでは, PyTorch を使ってディープラーニングの実践を行う.

    PyTorch の歴史のお話

    Facebook は PyTorch のほかに Caffe2 とよばれるディープラーニングのフレームワークを開発していた (初代 Caffe は UC Berkley の博士課程学生だった Yangqing Jia によって創られた). Caffe2 は 2018 年に PyTorch プロジェクトに合併された.

    また,2019 年 12 月,日本の Preferred Networks 社が開発していた Chainer も開発を終了し,PyTorch の開発チームと協業していくことが発表された (詳しくは プレスリリース を参照). PyTorch には,開発統合前から Chainer からインスパイアされた API がいくつもあり, Chainer の DNA は今も PyTorch に引き継がれているのである…!

    本格的なディープラーニングの計算に移る前に, PyTorch ライブラリを使って, GPU で計算を行うとはどういうものか,その入り口に触れてみよう.

    まずは,新しいノートブックを作成する. Jupyter のホーム画面の右上の "New" を押し,"conda_pytorch_p36" という環境を選択したうえで,新規ノートブックを作成する (figure_title). "conda_pytorch_p36" の仮想環境には, PyTorch がインストール済みである.

    新規ノートブックの作成. "conda_pytorch_p36" の環境を選択する.

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    python
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    python
    x = torch.rand(3,3)
    -print(x)
    x = torch.rand(3,3)
    -print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    python
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    python
    z = x + y
    -print(z)
    z = x + y
    -print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    python
    z = z.to("cpu")
    -print(z)
    z = z.to("cpu")
    -print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    完成した Jupyter Notebook は /handson/mnist/pytorch/pytorch_get_started.ipynb にある. Jupyter の画面右上の "Upload" からこのファイルをアップロードして,コードを走らせることが可能である.

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    python
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -
    -%time z = torch.matmul(x,y)
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -
    -%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    python
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    -
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    -
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    このベンチマークでは, dtype=torch.float32 と指定することで,32bit の浮動小数点型を用いている. ディープラーニングの学習および推論の計算には,32bit 型,場合によっては 16bit 型が使われるのが一般的である. これの主な理由として,教師データやミニバッチに起因するノイズが,浮動小数点の精度よりも大きいことがあげられる. 32bit/16bit を採用することで,メモリー消費を抑えたり,計算速度の向上が達成できる.

    上記のベンチマークから,GPU を用いることで,約 10 倍のスピードアップを実現することができた. スピードアップの性能は,演算の種類や行列のサイズに依存する. 行列積は,そのなかでも最も速度向上が見込まれる演算の一つである.

    実践ディープラーニング! MNIST 手書き数字認識タスク

    ここまで,AWS 上でディープラーニングの計算をするための概念や前提知識をながながと説明してきたが,ついにここからディープラーニングの計算を実際に走らせてみる.

    ここでは,機械学習のタスクで最も初歩的かつ有名な MNIST データセットを使った数字認識を扱う (figure_title). これは,0 から 9 までの手書きの数字の画像が与えられ,その数字が何の数字なのかを当てる,というシンプルなタスクである.

    MNIST 手書き数字データセット

    今回は, MNIST 文字認識タスクを,畳み込みニューラルネットワーク (Convolutional Neural Network; CNN) を使って解く. ソースコードは /handson/minist/pytorch/ にある mnist.ipynbsimple_mnist.py である. なお,このプログラムは, PyTorch の公式 Example Project 集 を参考に,多少の改変を行ったものである.

    まずは,カスタムのクラスや関数が定義された simple_mnist.py をアップロードしよう (figure_title). 画面右上の "Upload" ボタンをクリックし,ファイルを選択することでアップロードができる. この Python プログラムの中に,CNN のモデルや,学習の各イテレーションにおけるパラメータの更新などが記述されている. 今回はこの中身を説明することはしないが,興味のある読者は自身でソースコードを読んでみるとよい.

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    python
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    -
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    -
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    python
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    -
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    -
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    -
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    -
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    python
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    -
    -print("Example data size:", example_data.shape)
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    -
    -print("Example data size:", example_data.shape)
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    python
    model = Model()
    -model.to("cuda") # load to GPU
    model = Model()
    -model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    python
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\\n")
    -
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\\n")
    -
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    python
    model.eval()
    -
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    model.eval()
    -
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は (#handson_01_delete_stack) 参照).

    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    ',154);function w(P,x,I,T,N,M){const a=n;return v(),f("div",null,[S,k(a,{readTime:"14",words:"3.2k"}),z])}const H=_(C,[["render",w]]);export{$ as __pageData,H as default}; diff --git a/assets/development_aws_handson-jupyter.md.7f479319.lean.js b/assets/development_aws_handson-jupyter.md.7f479319.lean.js deleted file mode 100644 index 1642bc86..00000000 --- a/assets/development_aws_handson-jupyter.md.7f479319.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as r,f as c,g as y,h as i,i as d,j as u,k as m,l as h,m as b,n as B,o as A,p as g}from"./chunks/mnist_prediction.4ba5b405.js";import{_,o as v,c as f,H as k,k as s,a as D,Q as q}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Hands-on #2: AWS でディープラーニングを実践","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-jupyter.md","filePath":"development/aws/handson-jupyter.md","lastUpdated":1695377563000}'),C={name:"development/aws/handson-jupyter.md"},S=s("h1",{id:"hands-on-2-aws-でディープラーニングを実践",tabindex:"-1"},[D("Hands-on #2: AWS でディープラーニングを実践 "),s("a",{class:"header-anchor",href:"#hands-on-2-aws-でディープラーニングを実践","aria-label":'Permalink to "Hands-on \\#2: AWS でディープラーニングを実践"'},"​")],-1),z=q("",154);function w(P,x,I,T,N,M){const a=n;return v(),f("div",null,[S,k(a,{readTime:"14",words:"3.2k"}),z])}const H=_(C,[["render",w]]);export{$ as __pageData,H as default}; diff --git a/assets/development_aws_handson-jupyter.md.e87bcd1f.js b/assets/development_aws_handson-jupyter.md.e87bcd1f.js new file mode 100644 index 00000000..3087e706 --- /dev/null +++ b/assets/development_aws_handson-jupyter.md.e87bcd1f.js @@ -0,0 +1,247 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as r,f as c,g as y,h as i,i as d,j as A,k as u,l as m,m as C,n as D,o as F,p as h}from"./chunks/mnist_prediction.4ba5b405.js";import{_ as b,o as g,c as E,H as B,k as s,a as _,Q as v}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Hands-on #2: AWS でディープラーニングを実践","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-jupyter.md","filePath":"development/aws/handson-jupyter.md","lastUpdated":1699051935000}'),k={name:"development/aws/handson-jupyter.md"},f=s("h1",{id:"hands-on-2-aws-でディープラーニングを実践",tabindex:"-1"},[_("Hands-on #2: AWS でディープラーニングを実践 "),s("a",{class:"header-anchor",href:"#hands-on-2-aws-でディープラーニングを実践","aria-label":'Permalink to "Hands-on \\#2: AWS でディープラーニングを実践"'},"​")],-1),q=v('

    準備

    ハンズオン第二回では, GPU を搭載した EC2 インスタンスを起動し,深層学習モデルの学習と推論を実行する演習を行う.

    ハンズオンのソースコードは GitHub の handson/mnist に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. それ以外に必要な準備はない.

    初期状態の AWS アカウントでは, GPU 搭載の G タイプのインスタンスの起動上限が 0 になっていることがある. これを確認するには, AWS コンソールから EC2 の画面を開き,左のメニューから Limits を選択する. その中の Running On-Demand All G instances という数字が G インスタンスの起動上限を表している.

    もし,これが 0 になっていた場合は, AWS の自動申請フォームから上限緩和のリクエストを送る必要がある. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,東京 (ap-northeast-1) リージョンでは 0.71 $/hour のコストが発生する.

    AWS Educate Starter Account を使用している読者へ: 執筆時点においては, Starter Account には GPU 搭載型インスタンスを起動できないという制限が設けられている. したがって, Starter Account のユーザーはこのハンズオンを実行することはできない. 興味のある読者は,制限のない一般アカウントを自分自身で取得する必要があることに注意.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#2で作製するアプリケーションのアーキテクチャ

    図の多くの部分が,第一回ハンズオンで作成したアプリケーションと共通していることに気がつくだろう. 少しの変更で,簡単にディープラーニングを走らせる環境を構築することができるのである!主な変更点は次の3点である.

    • GPU を搭載した g4dn.xlarge インスタンスタイプを使用

    • ディープラーニングに使うプログラムがあらかじめインストールされた DLAMI (後述) を使用

    • SSH にポートフォワーディングのオプションつけてサーバーに接続し,サーバーで起動している Jupyter Notebook (後述) を使ってプログラムを書いたり実行したりする

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    python
    class Ec2ForDl(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class Ec2ForDl(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, (#sec_scientific_computing) ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

    • ここでは,Deep Learning 用の諸々のソフトウェアがプリンストールされた AMI (Deep Learning Amazon Machine Image; DLAMI) を選択している (第一回では,Amazon Linux という AMI を使用していた). 使用する AMI の ID は リージョンごとに指定する必要があり,ここでは us-east-1ap-northeast-1 でそれぞれ定義している.

    DLAMI という新しい概念が出てきたので,説明しよう.

    AMI が us-east-1ap-northeast-1 でしか定義されていないので,提供されているコードはこの二つのリージョンのみでデプロイ可能である. もしほかのリージョンを利用したい場合は, AMI の ID を自身で検索し,コードに書き込む必要がある.

    DLAMI (Deep Learning Amazon Machine Image)

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    最も low-level なレイヤーとしては, GPU ドライバー がインストールされている. GPU ドライバーなしには OS は GPU とコマンドのやり取りをすることができない. 次のレイヤーが CUDAcuDNN である. CUDA は, NVIDIA 社が開発した, GPU 上で汎用コンピューティングを行うための言語であり, C++ 言語を拡張したシンタックスを備える. cuDNN は CUDA で書かれたディープラーニングのライブラリであり,n 次元の畳み込みなどの演算が実装されている. ここまでが, "Base" とよばれるタイプの DLAMI の中身である.

    これに加えて, "Conda" とよばれるタイプには, "Base" のプログラム基盤の上に, TensorFlowPyTorch などのライブラリがインストールされている. さらに, Anaconda による仮想環境を使うことによって, TensorFlow の環境・ PyTorch の環境・ MxNet の環境など,フレームワークを簡単に切り替えることができる (これについては,後のハンズオンで触れる). また, Jupyter Notebook もインストール済みである.

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    +
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    +
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    SSH ログインコマンドの <IP address> 部分は自身のインスタンスの IP アドレスを代入することを忘れずに.

    本書の提供している Docker を使ってデプロイを実行した人へ

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    Jupyter Notebook とは,インタラクティブに Python のプログラムを書いたり実行したりするためのツールである. Jupyter は GUI としてウェブブラウザを介してアクセスする形式をとっており,まるでノートを書くように,プロットやテーブルのデータも美しく表示することができる (figure_title). Python に慣れている読者は,きっと一度は使ったことがあるだろう.

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    sh
    $ cd ~ # go to home directory
    +$ jupyter notebook
    $ cd ~ # go to home directory
    +$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    Jupyter Notebook の使い方 (超簡易版)

    • Shift + Enter: セルを実行

    • Esc: Command mode に遷移

    • メニューバーの "+" ボタン または Command mode で A ⇒ セルを追加

    • メニューバーの "ハサミ" ボタン または Command mode で X ⇒ セルを削除

    ショートカットの一覧などは Ventsislav Yordanov 氏によるブログ が参考になる.

    PyTorch はじめの一歩

    PyTorch は Facebook AI Research LAB (FAIR) が中心となって開発を進めている,オープンソースのディープラーニングのライブラリである. PyTorch は 有名な例で言えば Tesla 社の自動運転プロジェクトなどで使用されており,執筆時点において最も人気の高いディープラーニングライブラリの一つである. 本ハンズオンでは, PyTorch を使ってディープラーニングの実践を行う.

    PyTorch の歴史のお話

    Facebook は PyTorch のほかに Caffe2 とよばれるディープラーニングのフレームワークを開発していた (初代 Caffe は UC Berkley の博士課程学生だった Yangqing Jia によって創られた). Caffe2 は 2018 年に PyTorch プロジェクトに合併された.

    また,2019 年 12 月,日本の Preferred Networks 社が開発していた Chainer も開発を終了し,PyTorch の開発チームと協業していくことが発表された (詳しくは プレスリリース を参照). PyTorch には,開発統合前から Chainer からインスパイアされた API がいくつもあり, Chainer の DNA は今も PyTorch に引き継がれているのである…!

    本格的なディープラーニングの計算に移る前に, PyTorch ライブラリを使って, GPU で計算を行うとはどういうものか,その入り口に触れてみよう.

    まずは,新しいノートブックを作成する. Jupyter のホーム画面の右上の "New" を押し,"conda_pytorch_p36" という環境を選択したうえで,新規ノートブックを作成する (figure_title). "conda_pytorch_p36" の仮想環境には, PyTorch がインストール済みである.

    新規ノートブックの作成. "conda_pytorch_p36" の環境を選択する.

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    python
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    python
    x = torch.rand(3,3)
    +print(x)
    x = torch.rand(3,3)
    +print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    python
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    python
    z = x + y
    +print(z)
    z = x + y
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    python
    z = z.to("cpu")
    +print(z)
    z = z.to("cpu")
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    完成した Jupyter Notebook は /handson/mnist/pytorch/pytorch_get_started.ipynb にある. Jupyter の画面右上の "Upload" からこのファイルをアップロードして,コードを走らせることが可能である.

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    python
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +
    +%time z = torch.matmul(x,y)
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +
    +%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    python
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
    +
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
    +
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    このベンチマークでは, dtype=torch.float32 と指定することで,32bit の浮動小数点型を用いている. ディープラーニングの学習および推論の計算には,32bit 型,場合によっては 16bit 型が使われるのが一般的である. これの主な理由として,教師データやミニバッチに起因するノイズが,浮動小数点の精度よりも大きいことがあげられる. 32bit/16bit を採用することで,メモリー消費を抑えたり,計算速度の向上が達成できる.

    上記のベンチマークから,GPU を用いることで,約 10 倍のスピードアップを実現することができた. スピードアップの性能は,演算の種類や行列のサイズに依存する. 行列積は,そのなかでも最も速度向上が見込まれる演算の一つである.

    実践ディープラーニング! MNIST 手書き数字認識タスク

    ここまで,AWS 上でディープラーニングの計算をするための概念や前提知識をながながと説明してきたが,ついにここからディープラーニングの計算を実際に走らせてみる.

    ここでは,機械学習のタスクで最も初歩的かつ有名な MNIST データセットを使った数字認識を扱う (figure_title). これは,0 から 9 までの手書きの数字の画像が与えられ,その数字が何の数字なのかを当てる,というシンプルなタスクである.

    MNIST 手書き数字データセット

    今回は, MNIST 文字認識タスクを,畳み込みニューラルネットワーク (Convolutional Neural Network; CNN) を使って解く. ソースコードは /handson/minist/pytorch/ にある mnist.ipynbsimple_mnist.py である. なお,このプログラムは, PyTorch の公式 Example Project 集 を参考に,多少の改変を行ったものである.

    まずは,カスタムのクラスや関数が定義された simple_mnist.py をアップロードしよう (figure_title). 画面右上の "Upload" ボタンをクリックし,ファイルを選択することでアップロードができる. この Python プログラムの中に,CNN のモデルや,学習の各イテレーションにおけるパラメータの更新などが記述されている. 今回はこの中身を説明することはしないが,興味のある読者は自身でソースコードを読んでみるとよい.

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    python
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
    +
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
    +
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    python
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
    +
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
    +
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    python
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
    +
    +print("Example data size:", example_data.shape)
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
    +
    +print("Example data size:", example_data.shape)
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    python
    model = Model()
    +model.to("cuda") # load to GPU
    model = Model()
    +model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    python
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\\n")
    +
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\\n")
    +
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    python
    model.eval()
    +
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    model.eval()
    +
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は (#handson_01_delete_stack) 参照).

    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    ',154);function S(P,x,I,w,T,N){const a=n;return g(),E("div",null,[f,B(a,{readTime:"14",words:"3.2k"}),q])}const $=b(k,[["render",S]]);export{L as __pageData,$ as default}; diff --git a/assets/development_aws_handson-jupyter.md.e87bcd1f.lean.js b/assets/development_aws_handson-jupyter.md.e87bcd1f.lean.js new file mode 100644 index 00000000..3ff4ebd7 --- /dev/null +++ b/assets/development_aws_handson-jupyter.md.e87bcd1f.lean.js @@ -0,0 +1 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as r,f as c,g as y,h as i,i as d,j as A,k as u,l as m,m as C,n as D,o as F,p as h}from"./chunks/mnist_prediction.4ba5b405.js";import{_ as b,o as g,c as E,H as B,k as s,a as _,Q as v}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Hands-on #2: AWS でディープラーニングを実践","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-jupyter.md","filePath":"development/aws/handson-jupyter.md","lastUpdated":1699051935000}'),k={name:"development/aws/handson-jupyter.md"},f=s("h1",{id:"hands-on-2-aws-でディープラーニングを実践",tabindex:"-1"},[_("Hands-on #2: AWS でディープラーニングを実践 "),s("a",{class:"header-anchor",href:"#hands-on-2-aws-でディープラーニングを実践","aria-label":'Permalink to "Hands-on \\#2: AWS でディープラーニングを実践"'},"​")],-1),q=v("",154);function S(P,x,I,w,T,N){const a=n;return g(),E("div",null,[f,B(a,{readTime:"14",words:"3.2k"}),q])}const $=b(k,[["render",S]]);export{L as __pageData,$ as default}; diff --git a/assets/development_aws_handson-qabot.md.27ff1082.js b/assets/development_aws_handson-qabot.md.27ff1082.js new file mode 100644 index 00000000..56aa6286 --- /dev/null +++ b/assets/development_aws_handson-qabot.md.27ff1082.js @@ -0,0 +1,172 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as r,f as c,g as i,h as y,i as u,j as d}from"./chunks/ask_many_output.0bb19110.js";import{_ as A,o as b,c as h,H as C,k as s,a as m,Q as D}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Hands-on #3: AWS で自動質問回答ボットを走らせる","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-qabot.md","filePath":"development/aws/handson-qabot.md","lastUpdated":1699051935000}'),F={name:"development/aws/handson-qabot.md"},E=s("h1",{id:"hands-on-3-aws-で自動質問回答ボットを走らせる",tabindex:"-1"},[m("Hands-on #3: AWS で自動質問回答ボットを走らせる "),s("a",{class:"header-anchor",href:"#hands-on-3-aws-で自動質問回答ボットを走らせる","aria-label":'Permalink to "Hands-on \\#3: AWS で自動質問回答ボットを走らせる"'},"​")],-1),B=D('

    ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.

    通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 ( (#sec_aws_batch)) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.

    Fargate

    ハンズオンに入っていく前に, Fargate という AWS の機能を知っておく必要がある (figure_title).

    Fargate のアイコン

    ECS の概要を示した (#ecs_overview) をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. EC2 あるいは Fargate のいずれかである. EC2 を用いた場合は,先の章 ( (#sec_first_ec2), (#sec_jupyter_and_deep_learning)) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 ( (#sec_aws_batch)) で説明することにする.

    Fargate とは, ECS での利用に特化して設計された,コンテナを使用した計算タスクを走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は docker run のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.

    Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは 公式ドキュメンテーション "Amazon ECS on AWS Fargate" 参照). クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.

    以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.

    厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.

    準備

    ハンズオンのソースコードは GitHub の handson/qa-bot にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \\"the world's most famous equation\\". He received the 1921 Nobel Prize in Physics \\"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \\"the world's most famous equation\\". He received the 1921 Nobel Prize in Physics \\"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    answer: 1921
    +

    人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

    今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    sh
    $ docker run tomomano/qabot "\${context}" "\${question}" foo --no_save
    $ docker run tomomano/qabot "\${context}" "\${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    json
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    sh
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "\${context}" "\${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "\${context}" "\${question}" foo --no_save

    出力:

    json
    {
    +    "score": 0.5235594527494207,
    +    "start": 470,
    +    "end": 506,
    +    "answer": "his services to theoretical physics,"
    +}
    {
    +    "score": 0.5235594527494207,
    +    "start": 470,
    +    "end": 506,
    +    "answer": "his services to theoretical physics,"
    +}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    今回提供する Q-A ボットの Docker のソースコードは https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile にある.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,以下のような設計である.

    • クライアントは,質問を AWS 上のアプリケーションに送信する.

    • 質問のタスクは ECS によって処理される.

    • ECS は, Docker Hub から,イメージをダウンロードする.

    • 次に,ECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.

      • このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.
    • ジョブが実行される.

    • ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.

    • 最後に,クライアントは DynamoDB から質問への回答を読み取る.

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    python
    class EcsClusterQaBot(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
    +
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
    +
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
    +
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
    +
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    class EcsClusterQaBot(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
    +
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
    +
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
    +
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
    +
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

    • ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.

    • ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.

    • ここで,実行するタスクを定義している (task definition).

    • ここで, タスクの実行で使用する Docker イメージを定義している.

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    python
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
    +
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
    +
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
    +
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
    +
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.

    このコードで cpu=1024 と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は 公式ドキュメンテーション "Amazon ECS on AWS Fargate" を参照のこと.

    CPU ユニットと 指定可能なメモリー量の換算表

    CPU ユニット

    メモリーの値

    256 (.25 vCPU)

    0.5 GB, 1 GB, 2 GB

    512 (.5 vCPU)

    1 GB, 2 GB, 3 GB, 4 GB

    1024 (1 vCPU)

    2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB

    2048 (2 vCPU)

    Between 4 GB and 16 GB in 1-GB increments

    4096 (4 vCPU)

    Between 8 GB and 30 GB in 1-GB increments

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. figure_title で, FARGATE という文字の下に 0 Running tasks, 0 Pending tasks と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.

    ECS コンソール画面

    続いて,この画面の左のメニューバーから Task Definitions という項目を見つけ,クリックしよう. 移動した先のページで EcsClusterQaBotEcsClusterQaBotTaskDefXXXX という項目が見つかるので,開く. 開いた先のページをスクロールすると figure_title に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.

    Task definition の確認

    タスクの実行

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, "Tasks" という名前のタブがあるので,それを開く (figure_title). すると,実行中のタスクの一覧が表示されるだろう.

    ECS のタスクの実行状況をモニタリング

    figure_title で見て取れるように, "Last status = Pending" となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.

    しばらく待つうちに, Status が "RUNNING" に遷移し,計算が始まる. 計算が終わると, Status は "STOPPED" に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.

    figure_title の画面から, "Task" の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (figure_title). "Last status", "Platform version" など,タスクの情報が表示されている. また, "Logs" のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.

    質問タスクの実行結果

    さて, run_task.py を実行したコマンドラインに戻ってきてみると, figure_title のような出力が得られているはずである. "Momotaro" という正しい回答が返ってきている!

    質問タスクの実行結果

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    sh
    $ cdk destroy
    $ cdk destroy
    ',102);function g(q,f,k,_,v,w){const a=n;return b(),h("div",null,[E,C(a,{readTime:"11",words:"2.5k"}),B])}const U=A(F,[["render",g]]);export{$ as __pageData,U as default}; diff --git a/assets/development_aws_handson-qabot.md.27ff1082.lean.js b/assets/development_aws_handson-qabot.md.27ff1082.lean.js new file mode 100644 index 00000000..01fb14a6 --- /dev/null +++ b/assets/development_aws_handson-qabot.md.27ff1082.lean.js @@ -0,0 +1 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as l,b as o,c as e,d as t,e as r,f as c,g as i,h as y,i as u,j as d}from"./chunks/ask_many_output.0bb19110.js";import{_ as A,o as b,c as h,H as C,k as s,a as m,Q as D}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Hands-on #3: AWS で自動質問回答ボットを走らせる","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-qabot.md","filePath":"development/aws/handson-qabot.md","lastUpdated":1699051935000}'),F={name:"development/aws/handson-qabot.md"},E=s("h1",{id:"hands-on-3-aws-で自動質問回答ボットを走らせる",tabindex:"-1"},[m("Hands-on #3: AWS で自動質問回答ボットを走らせる "),s("a",{class:"header-anchor",href:"#hands-on-3-aws-で自動質問回答ボットを走らせる","aria-label":'Permalink to "Hands-on \\#3: AWS で自動質問回答ボットを走らせる"'},"​")],-1),B=D("",102);function g(q,f,k,_,v,w){const a=n;return b(),h("div",null,[E,C(a,{readTime:"11",words:"2.5k"}),B])}const U=A(F,[["render",g]]);export{$ as __pageData,U as default}; diff --git a/assets/development_aws_handson-qabot.md.3c125433.js b/assets/development_aws_handson-qabot.md.3c125433.js deleted file mode 100644 index 72b311a4..00000000 --- a/assets/development_aws_handson-qabot.md.3c125433.js +++ /dev/null @@ -1,172 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as o,c as e,d as t,e as r,f as c,g as i,h as y,i as d,j as u}from"./chunks/ask_many_output.0bb19110.js";import{_ as h,o as b,c as m,H as A,k as s,a as B,Q as f}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Hands-on #3: AWS で自動質問回答ボットを走らせる","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-qabot.md","filePath":"development/aws/handson-qabot.md","lastUpdated":1695377563000}'),g={name:"development/aws/handson-qabot.md"},q=s("h1",{id:"hands-on-3-aws-で自動質問回答ボットを走らせる",tabindex:"-1"},[B("Hands-on #3: AWS で自動質問回答ボットを走らせる "),s("a",{class:"header-anchor",href:"#hands-on-3-aws-で自動質問回答ボットを走らせる","aria-label":'Permalink to "Hands-on \\#3: AWS で自動質問回答ボットを走らせる"'},"​")],-1),k=f('

    ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.

    通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 ( (#sec_aws_batch)) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.

    Fargate

    ハンズオンに入っていく前に, Fargate という AWS の機能を知っておく必要がある (figure_title).

    Fargate のアイコン

    ECS の概要を示した (#ecs_overview) をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. EC2 あるいは Fargate のいずれかである. EC2 を用いた場合は,先の章 ( (#sec_first_ec2), (#sec_jupyter_and_deep_learning)) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 ( (#sec_aws_batch)) で説明することにする.

    Fargate とは, ECS での利用に特化して設計された,コンテナを使用した計算タスクを走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は docker run のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.

    Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは 公式ドキュメンテーション "Amazon ECS on AWS Fargate" 参照). クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.

    以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.

    厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.

    準備

    ハンズオンのソースコードは GitHub の handson/qa-bot にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \\"the world's most famous equation\\". He received the 1921 Nobel Prize in Physics \\"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \\"the world's most famous equation\\". He received the 1921 Nobel Prize in Physics \\"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    answer: 1921
    -

    人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

    今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    sh
    $ docker run tomomano/qabot "\${context}" "\${question}" foo --no_save
    $ docker run tomomano/qabot "\${context}" "\${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    json
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    sh
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "\${context}" "\${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "\${context}" "\${question}" foo --no_save

    出力:

    json
    {
    -    "score": 0.5235594527494207,
    -    "start": 470,
    -    "end": 506,
    -    "answer": "his services to theoretical physics,"
    -}
    {
    -    "score": 0.5235594527494207,
    -    "start": 470,
    -    "end": 506,
    -    "answer": "his services to theoretical physics,"
    -}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    今回提供する Q-A ボットの Docker のソースコードは https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile にある.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,以下のような設計である.

    • クライアントは,質問を AWS 上のアプリケーションに送信する.

    • 質問のタスクは ECS によって処理される.

    • ECS は, Docker Hub から,イメージをダウンロードする.

    • 次に,ECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.

      • このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.
    • ジョブが実行される.

    • ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.

    • 最後に,クライアントは DynamoDB から質問への回答を読み取る.

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    python
    class EcsClusterQaBot(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    -
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    -
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    -
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    -
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    class EcsClusterQaBot(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    -
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    -
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    -
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    -
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

    • ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.

    • ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.

    • ここで,実行するタスクを定義している (task definition).

    • ここで, タスクの実行で使用する Docker イメージを定義している.

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    python
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    -
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    -
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    -
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    -
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.

    このコードで cpu=1024 と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は 公式ドキュメンテーション "Amazon ECS on AWS Fargate" を参照のこと.

    CPU ユニットと 指定可能なメモリー量の換算表

    CPU ユニット

    メモリーの値

    256 (.25 vCPU)

    0.5 GB, 1 GB, 2 GB

    512 (.5 vCPU)

    1 GB, 2 GB, 3 GB, 4 GB

    1024 (1 vCPU)

    2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB

    2048 (2 vCPU)

    Between 4 GB and 16 GB in 1-GB increments

    4096 (4 vCPU)

    Between 8 GB and 30 GB in 1-GB increments

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. figure_title で, FARGATE という文字の下に 0 Running tasks, 0 Pending tasks と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.

    ECS コンソール画面

    続いて,この画面の左のメニューバーから Task Definitions という項目を見つけ,クリックしよう. 移動した先のページで EcsClusterQaBotEcsClusterQaBotTaskDefXXXX という項目が見つかるので,開く. 開いた先のページをスクロールすると figure_title に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.

    Task definition の確認

    タスクの実行

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, "Tasks" という名前のタブがあるので,それを開く (figure_title). すると,実行中のタスクの一覧が表示されるだろう.

    ECS のタスクの実行状況をモニタリング

    figure_title で見て取れるように, "Last status = Pending" となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.

    しばらく待つうちに, Status が "RUNNING" に遷移し,計算が始まる. 計算が終わると, Status は "STOPPED" に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.

    figure_title の画面から, "Task" の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (figure_title). "Last status", "Platform version" など,タスクの情報が表示されている. また, "Logs" のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.

    質問タスクの実行結果

    さて, run_task.py を実行したコマンドラインに戻ってきてみると, figure_title のような出力が得られているはずである. "Momotaro" という正しい回答が返ってきている!

    質問タスクの実行結果

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    sh
    $ cdk destroy
    $ cdk destroy
    ',102);function _(v,C,D,w,E,P){const a=n;return b(),m("div",null,[q,A(a,{readTime:"11",words:"2.5k"}),k])}const F=h(g,[["render",_]]);export{$ as __pageData,F as default}; diff --git a/assets/development_aws_handson-qabot.md.3c125433.lean.js b/assets/development_aws_handson-qabot.md.3c125433.lean.js deleted file mode 100644 index 3fd87b0b..00000000 --- a/assets/development_aws_handson-qabot.md.3c125433.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as o,c as e,d as t,e as r,f as c,g as i,h as y,i as d,j as u}from"./chunks/ask_many_output.0bb19110.js";import{_ as h,o as b,c as m,H as A,k as s,a as B,Q as f}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const $=JSON.parse('{"title":"Hands-on #3: AWS で自動質問回答ボットを走らせる","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-qabot.md","filePath":"development/aws/handson-qabot.md","lastUpdated":1695377563000}'),g={name:"development/aws/handson-qabot.md"},q=s("h1",{id:"hands-on-3-aws-で自動質問回答ボットを走らせる",tabindex:"-1"},[B("Hands-on #3: AWS で自動質問回答ボットを走らせる "),s("a",{class:"header-anchor",href:"#hands-on-3-aws-で自動質問回答ボットを走らせる","aria-label":'Permalink to "Hands-on \\#3: AWS で自動質問回答ボットを走らせる"'},"​")],-1),k=f("",102);function _(v,C,D,w,E,P){const a=n;return b(),m("div",null,[q,A(a,{readTime:"11",words:"2.5k"}),k])}const F=h(g,[["render",_]]);export{$ as __pageData,F as default}; diff --git a/assets/development_aws_handson-serverless.md.330af1e8.js b/assets/development_aws_handson-serverless.md.330af1e8.js deleted file mode 100644 index 6c62970a..00000000 --- a/assets/development_aws_handson-serverless.md.330af1e8.js +++ /dev/null @@ -1,219 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as e,c as o,d as t,e as r,f as c,g as i,h as y,i as d,j as b,k as m,l as u}from"./chunks/s3_bucket_filelist.89f3f384.js";import{_ as A,o as h,c as B,H as _,k as s,a as v,Q as k}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"Hands-on #5: サーバーレス入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-serverless.md","filePath":"development/aws/handson-serverless.md","lastUpdated":1695377563000}'),g={name:"development/aws/handson-serverless.md"},f=s("h1",{id:"hands-on-5-サーバーレス入門",tabindex:"-1"},[v("Hands-on #5: サーバーレス入門 "),s("a",{class:"header-anchor",href:"#hands-on-5-サーバーレス入門","aria-label":'Permalink to "Hands-on \\#5: サーバーレス入門"'},"​")],-1),D=k('

    前章ではサーバーレスアーキテクチャの概要の説明を行った. 本章では,ハンズオン形式でサーバーレスクラウドを実際に動かしながら,具体的な使用方法を学んでいこう. 今回のハンズオンでは Lambda, S3, DynamoDB の三つのサーバーレスクラウドの構成要素に触れていく. それぞれについて,短いチュートリアルを用意してある.

    Lambda ハンズオン

    まずは, Lambda を実際に動かしてみよう. ハンズオンのソースコードは GitHub の handson/serverless/lambda に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して Python で書かれたコードを Lambda に登録する. 続いて STEP 2 では, Invoke API を使用して,同時にいくつもの Lambda を起動し,並列な計算を行う. Lambda のワークフローを体験する目的で最小限の設定である.

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    -
    -class SimpleLambda(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    -
    -class SimpleLambda(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

    • 次に, Lambda に <1> で書いた関数を配置している. パラメータの意味は,文字どおりの意味なので難しくはないが,以下に解説する.

      • runtime=_lambda.Runtime.PYTHON_3_7: ここでは, Python3.7 を使って上記で定義された関数を実行せよ,と指定している. Python3.7 のほかに, Node.js, Java, Ruby, Go などの言語を指定することが可能である.

      • code=_lambda.Code.from_inline(FUNC): 実行されるべき関数が書かれたコードを指定する. ここでは, FUNC=... で定義した文字列を渡しているが,文字列以外にもファイルのパスを渡すことも可能である.

      • handler="index.handler": これは,コードの中にいくつかのサブ関数が含まれているときに,メインとサブを区別するためのパラメータである. handler という名前の関数をメイン関数として実行せよ,という意味である.

      • memory_size=128: メモリーは 128MB を最大で使用することを指定している.

      • timeout=core.Duration.seconds(10) タイムアウト時間を 10 秒に設定している. 10 秒以内に関数の実行が終了しなかった場合,エラーが返される.

      • dead_letter_queue_enabled=True: アドバンストな設定なので説明は省略する.

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    Lambda コンソール - 関数の一覧

    今回のアプリケーションで作成したのが SimpleLambda で始まるランダムな名前のついた関数だ. 関数の名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. 先ほどプログラムの中で定義した Python の関数がエディターから確認できる. さらに下の方にスクロールすると,関数の各種設定も確認できる.

    Lambda コンソール - 関数の詳細

    Lambda で実行されるコードは, Lambda のコンソール画面 (figure_title) のエディターで編集することもできる. デバッグをするときなどは,こちらを直接いじる方が早い場合もある. その場合は, CDK のコードに行った編集を反映させなおすことを忘れずに.

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    sh
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    ....................................................................................................
    -Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    figure_title で "Invocations" が関数が何度実行されたかを意味している. たしかに 100 回実行されていることがわかる. さらに, "Concurrent executions" は何個のタスクが同時に行われたかを示している. ここでは 96 となっていることから,96 個のタスクが並列的に実行されたことを意味している (これが 100 とならないのは,タスクの開始のコマンドが送られたのが完全には同タイミングではないことに起因する).

    このように,非常にシンプルではあるが, Lambda を使うことで,同時並列的に処理を実行することのできるクラウドシステムを簡単に作ることができた.

    もしこのようなことを従来的な serverful なクラウドで行おうとした場合,クラスターのスケーリングなど多くのコードを書くことに加えて,いろいろなパラメータを調節する必要がある.

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • partition_key: すべての DynamoDB テーブルには Partition key が定義されていなければならない. Partition key とは,テーブル内の要素 (レコード) ごとに存在する固有の ID のことである. 同一の Partition key をもった要素がテーブルの中に二つ以上存在することはできない (注: Sort Key を使用している場合は除く.詳しくは 公式ドキュメンテーション "Core Components of Amazon DynamoDB" 参照). また, Partition key が定義されていない要素はテーブルの中に存在することはできない. ここでは, Partition key に item_id という名前をつけている.

    • billing_mode: ddb.BillingMode.PAY_PER_REQUEST を指定することで, On-demand Capacity Mode の DynamoDB が作成される. ほかに PROVISIONED というモードがあるが,これはかなり高度なケースを除いて使用しないだろう.

    • removal_policy: CloudFormation のスタックが消去されたときに, DynamoDB も一緒に消去されるかどうかを指定する. このコードでは DESTROY を選んでいるので,すべて消去される. ほかのオプションを選択すると,スタックを消去しても DynamoDB のバックアップを残す,などの動作を定義することができる.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    DynamoDB のコンソール (テーブルの一覧)

    今回のアプリケーションで作成したのが SimpleDynamoDb で始まるランダムな名前のついたテーブルだ. テーブルの名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. "Items" のタブをクリックすると,テーブルの中のレコードを確認できる. 現時点ではなにもデータを書き込んでいないので,空である.

    DynamoDB のコンソール (テーブルの詳細画面)

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    python
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    -
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    -
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    python
    import boto3
    -ddb = boto3.resource('dynamodb')
    -
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    import boto3
    -ddb = boto3.resource('dynamodb')
    -
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    python
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if key is None:
    -        key = os.path.basename(filename)
    -
    -    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if key is None:
    -        key = os.path.basename(filename)
    -
    -    bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    python
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if filename is None:
    -        filename = os.path.basename(key)
    -
    -    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if filename is None:
    -        filename = os.path.basename(key)
    -
    -    bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy
    `,124);function X(C,q,w,S,z,$){const a=n;return h(),B("div",null,[f,_(a,{readTime:"10",words:"2.4k"}),D])}const L=A(g,[["render",X]]);export{N as __pageData,L as default}; diff --git a/assets/development_aws_handson-serverless.md.330af1e8.lean.js b/assets/development_aws_handson-serverless.md.330af1e8.lean.js deleted file mode 100644 index 46e39a56..00000000 --- a/assets/development_aws_handson-serverless.md.330af1e8.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as e,c as o,d as t,e as r,f as c,g as i,h as y,i as d,j as b,k as m,l as u}from"./chunks/s3_bucket_filelist.89f3f384.js";import{_ as A,o as h,c as B,H as _,k as s,a as v,Q as k}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"Hands-on #5: サーバーレス入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-serverless.md","filePath":"development/aws/handson-serverless.md","lastUpdated":1695377563000}'),g={name:"development/aws/handson-serverless.md"},f=s("h1",{id:"hands-on-5-サーバーレス入門",tabindex:"-1"},[v("Hands-on #5: サーバーレス入門 "),s("a",{class:"header-anchor",href:"#hands-on-5-サーバーレス入門","aria-label":'Permalink to "Hands-on \\#5: サーバーレス入門"'},"​")],-1),D=k("",124);function X(C,q,w,S,z,$){const a=n;return h(),B("div",null,[f,_(a,{readTime:"10",words:"2.4k"}),D])}const L=A(g,[["render",X]]);export{N as __pageData,L as default}; diff --git a/assets/development_aws_handson-serverless.md.7fbfa1f9.js b/assets/development_aws_handson-serverless.md.7fbfa1f9.js new file mode 100644 index 00000000..326c596c --- /dev/null +++ b/assets/development_aws_handson-serverless.md.7fbfa1f9.js @@ -0,0 +1,219 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as e,c as o,d as t,e as r,f as c,g as i,h as y,i as d,j as m,k as b,l as u}from"./chunks/s3_bucket_filelist.89f3f384.js";import{_ as A,o as F,c as D,H as C,k as s,a as h,Q as _}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"Hands-on #5: サーバーレス入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-serverless.md","filePath":"development/aws/handson-serverless.md","lastUpdated":1699051935000}'),B={name:"development/aws/handson-serverless.md"},g=s("h1",{id:"hands-on-5-サーバーレス入門",tabindex:"-1"},[h("Hands-on #5: サーバーレス入門 "),s("a",{class:"header-anchor",href:"#hands-on-5-サーバーレス入門","aria-label":'Permalink to "Hands-on \\#5: サーバーレス入門"'},"​")],-1),v=_('

    前章ではサーバーレスアーキテクチャの概要の説明を行った. 本章では,ハンズオン形式でサーバーレスクラウドを実際に動かしながら,具体的な使用方法を学んでいこう. 今回のハンズオンでは Lambda, S3, DynamoDB の三つのサーバーレスクラウドの構成要素に触れていく. それぞれについて,短いチュートリアルを用意してある.

    Lambda ハンズオン

    まずは, Lambda を実際に動かしてみよう. ハンズオンのソースコードは GitHub の handson/serverless/lambda に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して Python で書かれたコードを Lambda に登録する. 続いて STEP 2 では, Invoke API を使用して,同時にいくつもの Lambda を起動し,並列な計算を行う. Lambda のワークフローを体験する目的で最小限の設定である.

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
    +
    +class SimpleLambda(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
    +
    +class SimpleLambda(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

    • 次に, Lambda に <1> で書いた関数を配置している. パラメータの意味は,文字どおりの意味なので難しくはないが,以下に解説する.

      • runtime=_lambda.Runtime.PYTHON_3_7: ここでは, Python3.7 を使って上記で定義された関数を実行せよ,と指定している. Python3.7 のほかに, Node.js, Java, Ruby, Go などの言語を指定することが可能である.

      • code=_lambda.Code.from_inline(FUNC): 実行されるべき関数が書かれたコードを指定する. ここでは, FUNC=... で定義した文字列を渡しているが,文字列以外にもファイルのパスを渡すことも可能である.

      • handler="index.handler": これは,コードの中にいくつかのサブ関数が含まれているときに,メインとサブを区別するためのパラメータである. handler という名前の関数をメイン関数として実行せよ,という意味である.

      • memory_size=128: メモリーは 128MB を最大で使用することを指定している.

      • timeout=core.Duration.seconds(10) タイムアウト時間を 10 秒に設定している. 10 秒以内に関数の実行が終了しなかった場合,エラーが返される.

      • dead_letter_queue_enabled=True: アドバンストな設定なので説明は省略する.

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    Lambda コンソール - 関数の一覧

    今回のアプリケーションで作成したのが SimpleLambda で始まるランダムな名前のついた関数だ. 関数の名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. 先ほどプログラムの中で定義した Python の関数がエディターから確認できる. さらに下の方にスクロールすると,関数の各種設定も確認できる.

    Lambda コンソール - 関数の詳細

    Lambda で実行されるコードは, Lambda のコンソール画面 (figure_title) のエディターで編集することもできる. デバッグをするときなどは,こちらを直接いじる方が早い場合もある. その場合は, CDK のコードに行った編集を反映させなおすことを忘れずに.

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    sh
    ....................................................................................................
    +Submitted 100 tasks to Lambda!
    ....................................................................................................
    +Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    figure_title で "Invocations" が関数が何度実行されたかを意味している. たしかに 100 回実行されていることがわかる. さらに, "Concurrent executions" は何個のタスクが同時に行われたかを示している. ここでは 96 となっていることから,96 個のタスクが並列的に実行されたことを意味している (これが 100 とならないのは,タスクの開始のコマンドが送られたのが完全には同タイミングではないことに起因する).

    このように,非常にシンプルではあるが, Lambda を使うことで,同時並列的に処理を実行することのできるクラウドシステムを簡単に作ることができた.

    もしこのようなことを従来的な serverful なクラウドで行おうとした場合,クラスターのスケーリングなど多くのコードを書くことに加えて,いろいろなパラメータを調節する必要がある.

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • partition_key: すべての DynamoDB テーブルには Partition key が定義されていなければならない. Partition key とは,テーブル内の要素 (レコード) ごとに存在する固有の ID のことである. 同一の Partition key をもった要素がテーブルの中に二つ以上存在することはできない (注: Sort Key を使用している場合は除く.詳しくは 公式ドキュメンテーション "Core Components of Amazon DynamoDB" 参照). また, Partition key が定義されていない要素はテーブルの中に存在することはできない. ここでは, Partition key に item_id という名前をつけている.

    • billing_mode: ddb.BillingMode.PAY_PER_REQUEST を指定することで, On-demand Capacity Mode の DynamoDB が作成される. ほかに PROVISIONED というモードがあるが,これはかなり高度なケースを除いて使用しないだろう.

    • removal_policy: CloudFormation のスタックが消去されたときに, DynamoDB も一緒に消去されるかどうかを指定する. このコードでは DESTROY を選んでいるので,すべて消去される. ほかのオプションを選択すると,スタックを消去しても DynamoDB のバックアップを残す,などの動作を定義することができる.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    DynamoDB のコンソール (テーブルの一覧)

    今回のアプリケーションで作成したのが SimpleDynamoDb で始まるランダムな名前のついたテーブルだ. テーブルの名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. "Items" のタブをクリックすると,テーブルの中のレコードを確認できる. 現時点ではなにもデータを書き込んでいないので,空である.

    DynamoDB のコンソール (テーブルの詳細画面)

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    python
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
    +
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
    +
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    python
    import boto3
    +ddb = boto3.resource('dynamodb')
    +
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)
    import boto3
    +ddb = boto3.resource('dynamodb')
    +
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    python
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if key is None:
    +        key = os.path.basename(filename)
    +
    +    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if key is None:
    +        key = os.path.basename(filename)
    +
    +    bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    python
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if filename is None:
    +        filename = os.path.basename(key)
    +
    +    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if filename is None:
    +        filename = os.path.basename(key)
    +
    +    bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy
    `,124);function E(k,f,X,q,S,w){const a=n;return F(),D("div",null,[g,C(a,{readTime:"10",words:"2.4k"}),v])}const L=A(B,[["render",E]]);export{N as __pageData,L as default}; diff --git a/assets/development_aws_handson-serverless.md.7fbfa1f9.lean.js b/assets/development_aws_handson-serverless.md.7fbfa1f9.lean.js new file mode 100644 index 00000000..2e41b48f --- /dev/null +++ b/assets/development_aws_handson-serverless.md.7fbfa1f9.lean.js @@ -0,0 +1 @@ +import{_ as n}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as l,a as p,b as e,c as o,d as t,e as r,f as c,g as i,h as y,i as d,j as m,k as b,l as u}from"./chunks/s3_bucket_filelist.89f3f384.js";import{_ as A,o as F,c as D,H as C,k as s,a as h,Q as _}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const N=JSON.parse('{"title":"Hands-on #5: サーバーレス入門","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/handson-serverless.md","filePath":"development/aws/handson-serverless.md","lastUpdated":1699051935000}'),B={name:"development/aws/handson-serverless.md"},g=s("h1",{id:"hands-on-5-サーバーレス入門",tabindex:"-1"},[h("Hands-on #5: サーバーレス入門 "),s("a",{class:"header-anchor",href:"#hands-on-5-サーバーレス入門","aria-label":'Permalink to "Hands-on \\#5: サーバーレス入門"'},"​")],-1),v=_("",124);function E(k,f,X,q,S,w){const a=n;return F(),D("div",null,[g,C(a,{readTime:"10",words:"2.4k"}),v])}const L=A(B,[["render",E]]);export{N as __pageData,L as default}; diff --git a/assets/development_aws_index.md.1f9e71a6.js b/assets/development_aws_index.md.0fcf5beb.js similarity index 74% rename from assets/development_aws_index.md.1f9e71a6.js rename to assets/development_aws_index.md.0fcf5beb.js index 860de24d..6ac9b8c4 100644 --- a/assets/development_aws_index.md.1f9e71a6.js +++ b/assets/development_aws_index.md.0fcf5beb.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o}from"./chunks/earth_from_earth.8c108f53.js";import{_ as s,o as r,c as l,H as p,k as e,a as n,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"はじめに","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/index.md","filePath":"development/aws/index.md","lastUpdated":1695377563000}'),c={name:"development/aws/index.md"},d=e("h1",{id:"はじめに",tabindex:"-1"},[n("はじめに "),e("a",{class:"header-anchor",href:"#はじめに","aria-label":'Permalink to "はじめに"'},"​")],-1),h=i('

    本書の目的・内容

    本書は,東京大学計数工学科で 2021 年度 S1/S2 タームに開講されている"システム情報工学特論"の講義資料として作成された.

    本書の目的は,クラウドの初心者を対象とし,クラウドの基礎的な知識・概念を解説する. また, Amazon Web Services (以下, AWS) の提供するクラウド環境を実例として,具体的なクラウドの利用方法をハンズオンを通して学ぶ.

    とくに,科学・エンジニアリングの学生を対象として,研究などの目的でクラウドを利用するための実践的な手順を紹介する. 知識・理論の説明は最小限に留め,実践を行う中で必要な概念の解説を行う予定である. 読者が今後,研究などでクラウドを利用する際の,足がかりとなれば本書の目的は十分達成されたことになる.

    本書は以下のような三部構成になっている.

    本書の構成
    テーマハンズオン

    第一部 (1章-4章)

    クラウドの基礎

    • AWSに自分のサーバーを立ち上げる

    第二部 (5章-9章)

    クラウドを活用した機械学習

    • AWS と Jupyter を使って始めるディープラーニング

    • スケーラブルな自動質問回答ボットを作る

    • 並列化されたハイパーパラメータサーチの実装

    第三部 (10章-13章)

    サーバーレスアーキテクチャ入門

    • Lambda, DynamoDB, S3 の演習

    • 俳句を投稿する SNS "Bashoutter" を作る

    第一部は,クラウドの基礎となる概念・知識を解説する. セキュリティやネットワークなど,クラウドを利用する上で最低限おさえなければいけないポイントを説明する. ハンズオンでは,はじめての仮想サーバーを AWS に立ち上げる演習を行う.

    第二部では,クラウド上で科学計算 (とくに機械学習) を走らせるための入門となる知識・技術を解説する. あわせて, Docker とよばれる仮想計算環境の使用方法を紹介する. 一つ目のハンズオンでは, AWS のクラウドで Jupyter Notebook を起動し簡単な機械学習の計算を走らせる課題を実践する. 二つ目のハンズオンでは,深層学習を用いた自然言語処理により,質問に自動で回答を生成するボットを作成する. 最後に,複数台の GPU インスタンスからなるクラスターを起動し,並列に深層学習のハイパーパラメータサーチを行う方法を紹介する.

    第三部では,サーバーレスアーキテクチャとよばれる最新のクラウドのアーキテクチャを紹介する. これは,サーバーの処理能力を負荷に応じてより柔軟に拡大・縮小するための概念であり,それ以前 (Serverful としばしばよばれる) と質的に異なる設計思想をクラウドに導入するものである. ハンズオンでは,サーバーレスクラウドの主要なコンポーネントである Lambda, DynamoDB, S3 の演習を提供する. さらに,サーバーレスの技術を使用して簡単な SNS をクラウド上に作成する.

    これらの豊富なハンズオンにより, AWS 上にクラウドシステムを開発するための知識と技術が身につくはずである. いずれのハンズオンも,実用性を重視したものになっており,これらをベースにカスタマイズを施すことで様々な応用が可能である.

    本書のフィロソフィー

    本書のフィロソフィーを一言で表すなら, "ロケットで宇宙まで飛んでいって一度地球を眺めてみよう!" である.

    どういうことか?

    ここでいう"地球"とは,クラウドコンピューティングの全体像のことである. 言うまでもなく,クラウドという技術は非常に広範かつ複雑な概念で,幾多の情報技術・ハードウェア・アルゴリズムが精緻に組み合わさってできた総体である. そして,今日では科学研究から日常のインフラ設備に至るまで,我々の社会の多くの部分がクラウド技術によって支えられている.

    ここでいう"ロケット"とはこの講義のことである. この講義では,ロケットに乗って宇宙まで飛び立ち,地球(クラウド)の全体を自身の目で眺めてもらう. その際,ロケットの成り立ちや仕組み (背後にある要素技術やプログラムのソースコード) を深くは問わない. 将来,自分が研究などの目的でクラウドを利用することになった際に,改めて学んでもらえば良い. 本書の目的はむしろ,クラウドの最先端に実際に触れ,そこからどんな景色が見えるか(どんな応用が可能か)を実感してもらうことである.

    そのような理由で,本書はクラウドの基礎から応用まで幅広いテーマを取り扱う. 第一部はクラウドの基礎から始め,第二部では一気にレベルアップし機械学習(深層学習)をクラウドで実行する手法を解説する. さらに第三部では,サーバーレス・アーキテクチャというここ数年のうちに確立した全く新しいクラウドの設計について解説する. それぞれで本一冊分以上の内容に相当するものであるが,本書はあえてこれらを一冊にまとめ連続的に俯瞰するという野心的な意図をもって執筆された.

    決して楽な搭乗体験ではないかもしれないが,このロケットにしがみついてきてもらえれば,とてもエキサイティングな景色が見られることを約束したい.

    宇宙からみた地球 (Image from NASA https://www.nasa.gov/image-feature/planet-of-clouds)

    AWS アカウント

    本書では,ハンズオン形式で AWS のクラウドを実際に動かす演習を提供する. 自分でハンズオンを実行してみたい読者は,各自で AWS のアカウントの作成をしていただく. AWS のアカウントの作成の仕方は巻末付録 ( (#sec:create_aws_account)) に簡単に記載したので,必要に応じて参照していただきたい.

    AWS にはいくつかの機能に対して無料利用枠が設定されており,いくつかのハンズオンは無料の範囲内で実行できる. 一方,ほかのハンズオン (とくに機械学習を扱うもの) では数ドル程度のコストが発生する. ハンズオンごとに発生するおおよそのコストについて記述があるので,注意をしながらハンズオンに取り組んでいただきたい.

    また,大学などの教育機関における講義で AWS を使用する際は, AWS Educate というプログラムを利用することも可能である. これは,講義の担当者が申請を行うことで,受講する学生に対し AWS クレジットが提供されるというプログラムである. AWS Educate を利用することで金銭的な負担なしに AWS を体験することができる. また,講義を経由せず個人でも AWS Educate に参加することも可能である. AWS Educate からは様々な学習教材が提供されているので,ぜひ活用してもらいたい.

    環境構築

    本書では, AWS 上にクラウドアプリケーションを展開するハンズオンを実施する. そこで紹介するプログラムを実行するためには,以下の計算機環境が必要である. インストールの方法については,巻末付録 ( (#sec:appendix_settingup)) に記してある. 必要に応じて参照し,環境構築を各自実施していただきたい.

    • UNIX 系コンソール: ハンズオンで紹介するコマンドを実行したり, SSH でサーバーにアクセスするため, UNIX 系のコンソール環境が必要である. Mac または Linux のユーザーは, OS に標準搭載のコンソール(ターミナルとも呼ばれる)を使用すればよい. Windows のユーザーは, Windows Subsystem for Linux (WSL) を使い, Linux の仮想環境のインストールを推奨する ( (#sec:install_wsl) 参照).

    • Docker: 本書では Docker とよばれる仮想計算環境の利用方法を解説する. インストール手順については (#sec:install_docker) を参照のこと.

    • Python: Version 3.6 以上をインストールする. とくに,ハンズオンでは venv モジュールを使用する. venv の使い方は (#venv_quick_guide) 参照のこと.

    • Node.js: version 12.0 以上 をインストールする.

    • AWS CLI: Version 2 をインストールする. インストール手順については (#aws_cli_install) 参照のこと.

    • AWS CDK: Version 1.100 以上をインストールする. Version 2 以降には未対応である. インストール手順については (#aws_cdk_install) 参照のこと.

    • AWS 認証鍵の設定: AWS API をコマンドラインから呼ぶには,認証鍵 (secret key) が設定されている必要がある. 認証鍵の設定については (#aws_cli_install) 参照のこと.

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は (#sec_handson_docker) に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    • Python の基本的な理解: 本書では Python を使ってプログラムの作成を行う. 使用するライブラリは十分抽象化されており,関数の名前を見ただけで意味が明瞭なものがほとんどであるので, Python に詳しくなくても心配する必要はない.

    • Linux コマンドラインの基礎的な理解: クラウドを利用する際,クラウド上に立ち上がるサーバーは基本的に Linux である. Linux のコマンドラインについて知識があると,トラブルシュートなどが容易になる. 筆者のおすすめの参考書は The Linux Command Line by William Shotts である. ウェブで無料で読むことができるので,読んだことのない人はぜひ一読を.

    講義に関連する資料

    ハンズオンで使うプログラムや教科書のソースコードは以下のウェブページで公開している.

    本書で使用するノーテーションなど

    • コードやシェルのコマンドは monospace letter で記述する.

    • シェルに入力するコマンドは,それがシェルコマンドであると明示する目的で,先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力には $ はついていない点に留意する.

    また,以下のような形式で注意やチップスを提供する.

    追加のコメントなどを記す.

    発展的な議論やアイディアなどを紹介する.

    陥りやすいミスなどの注意事項を述べる.

    絶対に犯してはならないミスを指摘する.

    ',42);function u(m,_,g,S,A,b){const a=t;return r(),l("div",null,[d,p(a,{readTime:"4",words:"1.3k"}),h])}const q=s(c,[["render",u]]);export{w as __pageData,q as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o}from"./chunks/earth_from_earth.8c108f53.js";import{_ as s,o as r,c as l,H as p,k as e,a as n,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"はじめに","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/index.md","filePath":"development/aws/index.md","lastUpdated":1699051935000}'),c={name:"development/aws/index.md"},d=e("h1",{id:"はじめに",tabindex:"-1"},[n("はじめに "),e("a",{class:"header-anchor",href:"#はじめに","aria-label":'Permalink to "はじめに"'},"​")],-1),h=i('

    本書の目的・内容

    本書は,東京大学計数工学科で 2021 年度 S1/S2 タームに開講されている"システム情報工学特論"の講義資料として作成された.

    本書の目的は,クラウドの初心者を対象とし,クラウドの基礎的な知識・概念を解説する. また, Amazon Web Services (以下, AWS) の提供するクラウド環境を実例として,具体的なクラウドの利用方法をハンズオンを通して学ぶ.

    とくに,科学・エンジニアリングの学生を対象として,研究などの目的でクラウドを利用するための実践的な手順を紹介する. 知識・理論の説明は最小限に留め,実践を行う中で必要な概念の解説を行う予定である. 読者が今後,研究などでクラウドを利用する際の,足がかりとなれば本書の目的は十分達成されたことになる.

    本書は以下のような三部構成になっている.

    本書の構成
    テーマハンズオン

    第一部 (1章-4章)

    クラウドの基礎

    • AWSに自分のサーバーを立ち上げる

    第二部 (5章-9章)

    クラウドを活用した機械学習

    • AWS と Jupyter を使って始めるディープラーニング

    • スケーラブルな自動質問回答ボットを作る

    • 並列化されたハイパーパラメータサーチの実装

    第三部 (10章-13章)

    サーバーレスアーキテクチャ入門

    • Lambda, DynamoDB, S3 の演習

    • 俳句を投稿する SNS "Bashoutter" を作る

    第一部は,クラウドの基礎となる概念・知識を解説する. セキュリティやネットワークなど,クラウドを利用する上で最低限おさえなければいけないポイントを説明する. ハンズオンでは,はじめての仮想サーバーを AWS に立ち上げる演習を行う.

    第二部では,クラウド上で科学計算 (とくに機械学習) を走らせるための入門となる知識・技術を解説する. あわせて, Docker とよばれる仮想計算環境の使用方法を紹介する. 一つ目のハンズオンでは, AWS のクラウドで Jupyter Notebook を起動し簡単な機械学習の計算を走らせる課題を実践する. 二つ目のハンズオンでは,深層学習を用いた自然言語処理により,質問に自動で回答を生成するボットを作成する. 最後に,複数台の GPU インスタンスからなるクラスターを起動し,並列に深層学習のハイパーパラメータサーチを行う方法を紹介する.

    第三部では,サーバーレスアーキテクチャとよばれる最新のクラウドのアーキテクチャを紹介する. これは,サーバーの処理能力を負荷に応じてより柔軟に拡大・縮小するための概念であり,それ以前 (Serverful としばしばよばれる) と質的に異なる設計思想をクラウドに導入するものである. ハンズオンでは,サーバーレスクラウドの主要なコンポーネントである Lambda, DynamoDB, S3 の演習を提供する. さらに,サーバーレスの技術を使用して簡単な SNS をクラウド上に作成する.

    これらの豊富なハンズオンにより, AWS 上にクラウドシステムを開発するための知識と技術が身につくはずである. いずれのハンズオンも,実用性を重視したものになっており,これらをベースにカスタマイズを施すことで様々な応用が可能である.

    本書のフィロソフィー

    本書のフィロソフィーを一言で表すなら, "ロケットで宇宙まで飛んでいって一度地球を眺めてみよう!" である.

    どういうことか?

    ここでいう"地球"とは,クラウドコンピューティングの全体像のことである. 言うまでもなく,クラウドという技術は非常に広範かつ複雑な概念で,幾多の情報技術・ハードウェア・アルゴリズムが精緻に組み合わさってできた総体である. そして,今日では科学研究から日常のインフラ設備に至るまで,我々の社会の多くの部分がクラウド技術によって支えられている.

    ここでいう"ロケット"とはこの講義のことである. この講義では,ロケットに乗って宇宙まで飛び立ち,地球(クラウド)の全体を自身の目で眺めてもらう. その際,ロケットの成り立ちや仕組み (背後にある要素技術やプログラムのソースコード) を深くは問わない. 将来,自分が研究などの目的でクラウドを利用することになった際に,改めて学んでもらえば良い. 本書の目的はむしろ,クラウドの最先端に実際に触れ,そこからどんな景色が見えるか(どんな応用が可能か)を実感してもらうことである.

    そのような理由で,本書はクラウドの基礎から応用まで幅広いテーマを取り扱う. 第一部はクラウドの基礎から始め,第二部では一気にレベルアップし機械学習(深層学習)をクラウドで実行する手法を解説する. さらに第三部では,サーバーレス・アーキテクチャというここ数年のうちに確立した全く新しいクラウドの設計について解説する. それぞれで本一冊分以上の内容に相当するものであるが,本書はあえてこれらを一冊にまとめ連続的に俯瞰するという野心的な意図をもって執筆された.

    決して楽な搭乗体験ではないかもしれないが,このロケットにしがみついてきてもらえれば,とてもエキサイティングな景色が見られることを約束したい.

    宇宙からみた地球 (Image from NASA https://www.nasa.gov/image-feature/planet-of-clouds)

    AWS アカウント

    本書では,ハンズオン形式で AWS のクラウドを実際に動かす演習を提供する. 自分でハンズオンを実行してみたい読者は,各自で AWS のアカウントの作成をしていただく. AWS のアカウントの作成の仕方は巻末付録 ( (#sec:create_aws_account)) に簡単に記載したので,必要に応じて参照していただきたい.

    AWS にはいくつかの機能に対して無料利用枠が設定されており,いくつかのハンズオンは無料の範囲内で実行できる. 一方,ほかのハンズオン (とくに機械学習を扱うもの) では数ドル程度のコストが発生する. ハンズオンごとに発生するおおよそのコストについて記述があるので,注意をしながらハンズオンに取り組んでいただきたい.

    また,大学などの教育機関における講義で AWS を使用する際は, AWS Educate というプログラムを利用することも可能である. これは,講義の担当者が申請を行うことで,受講する学生に対し AWS クレジットが提供されるというプログラムである. AWS Educate を利用することで金銭的な負担なしに AWS を体験することができる. また,講義を経由せず個人でも AWS Educate に参加することも可能である. AWS Educate からは様々な学習教材が提供されているので,ぜひ活用してもらいたい.

    環境構築

    本書では, AWS 上にクラウドアプリケーションを展開するハンズオンを実施する. そこで紹介するプログラムを実行するためには,以下の計算機環境が必要である. インストールの方法については,巻末付録 ( (#sec:appendix_settingup)) に記してある. 必要に応じて参照し,環境構築を各自実施していただきたい.

    • UNIX 系コンソール: ハンズオンで紹介するコマンドを実行したり, SSH でサーバーにアクセスするため, UNIX 系のコンソール環境が必要である. Mac または Linux のユーザーは, OS に標準搭載のコンソール(ターミナルとも呼ばれる)を使用すればよい. Windows のユーザーは, Windows Subsystem for Linux (WSL) を使い, Linux の仮想環境のインストールを推奨する ( (#sec:install_wsl) 参照).

    • Docker: 本書では Docker とよばれる仮想計算環境の利用方法を解説する. インストール手順については (#sec:install_docker) を参照のこと.

    • Python: Version 3.6 以上をインストールする. とくに,ハンズオンでは venv モジュールを使用する. venv の使い方は (#venv_quick_guide) 参照のこと.

    • Node.js: version 12.0 以上 をインストールする.

    • AWS CLI: Version 2 をインストールする. インストール手順については (#aws_cli_install) 参照のこと.

    • AWS CDK: Version 1.100 以上をインストールする. Version 2 以降には未対応である. インストール手順については (#aws_cdk_install) 参照のこと.

    • AWS 認証鍵の設定: AWS API をコマンドラインから呼ぶには,認証鍵 (secret key) が設定されている必要がある. 認証鍵の設定については (#aws_cli_install) 参照のこと.

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は (#sec_handson_docker) に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    • Python の基本的な理解: 本書では Python を使ってプログラムの作成を行う. 使用するライブラリは十分抽象化されており,関数の名前を見ただけで意味が明瞭なものがほとんどであるので, Python に詳しくなくても心配する必要はない.

    • Linux コマンドラインの基礎的な理解: クラウドを利用する際,クラウド上に立ち上がるサーバーは基本的に Linux である. Linux のコマンドラインについて知識があると,トラブルシュートなどが容易になる. 筆者のおすすめの参考書は The Linux Command Line by William Shotts である. ウェブで無料で読むことができるので,読んだことのない人はぜひ一読を.

    講義に関連する資料

    ハンズオンで使うプログラムや教科書のソースコードは以下のウェブページで公開している.

    本書で使用するノーテーションなど

    • コードやシェルのコマンドは monospace letter で記述する.

    • シェルに入力するコマンドは,それがシェルコマンドであると明示する目的で,先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力には $ はついていない点に留意する.

    また,以下のような形式で注意やチップスを提供する.

    追加のコメントなどを記す.

    発展的な議論やアイディアなどを紹介する.

    陥りやすいミスなどの注意事項を述べる.

    絶対に犯してはならないミスを指摘する.

    ',42);function u(m,_,g,S,b,k){const a=t;return r(),l("div",null,[d,p(a,{readTime:"4",words:"1.3k"}),h])}const q=s(c,[["render",u]]);export{w as __pageData,q as default}; diff --git a/assets/development_aws_index.md.1f9e71a6.lean.js b/assets/development_aws_index.md.0fcf5beb.lean.js similarity index 85% rename from assets/development_aws_index.md.1f9e71a6.lean.js rename to assets/development_aws_index.md.0fcf5beb.lean.js index 10245e7d..138c4451 100644 --- a/assets/development_aws_index.md.1f9e71a6.lean.js +++ b/assets/development_aws_index.md.0fcf5beb.lean.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o}from"./chunks/earth_from_earth.8c108f53.js";import{_ as s,o as r,c as l,H as p,k as e,a as n,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"はじめに","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/index.md","filePath":"development/aws/index.md","lastUpdated":1695377563000}'),c={name:"development/aws/index.md"},d=e("h1",{id:"はじめに",tabindex:"-1"},[n("はじめに "),e("a",{class:"header-anchor",href:"#はじめに","aria-label":'Permalink to "はじめに"'},"​")],-1),h=i("",42);function u(m,_,g,S,A,b){const a=t;return r(),l("div",null,[d,p(a,{readTime:"4",words:"1.3k"}),h])}const q=s(c,[["render",u]]);export{w as __pageData,q as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o}from"./chunks/earth_from_earth.8c108f53.js";import{_ as s,o as r,c as l,H as p,k as e,a as n,Q as i}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const w=JSON.parse('{"title":"はじめに","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/index.md","filePath":"development/aws/index.md","lastUpdated":1699051935000}'),c={name:"development/aws/index.md"},d=e("h1",{id:"はじめに",tabindex:"-1"},[n("はじめに "),e("a",{class:"header-anchor",href:"#はじめに","aria-label":'Permalink to "はじめに"'},"​")],-1),h=i("",42);function u(m,_,g,S,b,k){const a=t;return r(),l("div",null,[d,p(a,{readTime:"4",words:"1.3k"}),h])}const q=s(c,[["render",u]]);export{w as __pageData,q as default}; diff --git a/assets/development_aws_license.md.5f519b50.js b/assets/development_aws_license.md.38e84b81.js similarity index 95% rename from assets/development_aws_license.md.5f519b50.js rename to assets/development_aws_license.md.38e84b81.js index bb328c67..1b1f04cd 100644 --- a/assets/development_aws_license.md.5f519b50.js +++ b/assets/development_aws_license.md.38e84b81.js @@ -1 +1 @@ -import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o,c,H as r,k as e,a as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const _="/assets/cc_by_nc_nd.c97a96cd.png",w=JSON.parse('{"title":"ライセンス","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/license.md","filePath":"development/aws/license.md","lastUpdated":1695377563000}'),d={name:"development/aws/license.md"},l=e("h1",{id:"ライセンス",tabindex:"-1"},[t("ライセンス "),e("a",{class:"header-anchor",href:"#ライセンス","aria-label":'Permalink to "ライセンス"'},"​")],-1),i=e("p",null,[t("本教科書およびハンズオンのソースコードは "),e("a",{href:"https://creativecommons.org/licenses/by-nc-nd/4.0/",target:"_blank",rel:"noreferrer"},"CC BY-NC-ND 4.0"),t(" に従うライセンスで公開しています.")],-1),p=e("p",null,"教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.",-1),m=e("p",null,[e("img",{src:_,alt:"cc_by_nc_nd"})],-1);function f(h,u,b,g,v,N){const a=s;return o(),c("div",null,[l,r(a,{readTime:"1",words:"62"}),i,p,m])}const B=n(d,[["render",f]]);export{w as __pageData,B as default}; +import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o,c,H as r,k as e,a as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const _="/assets/cc_by_nc_nd.c97a96cd.png",w=JSON.parse('{"title":"ライセンス","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/license.md","filePath":"development/aws/license.md","lastUpdated":1699051935000}'),d={name:"development/aws/license.md"},l=e("h1",{id:"ライセンス",tabindex:"-1"},[t("ライセンス "),e("a",{class:"header-anchor",href:"#ライセンス","aria-label":'Permalink to "ライセンス"'},"​")],-1),i=e("p",null,[t("本教科書およびハンズオンのソースコードは "),e("a",{href:"https://creativecommons.org/licenses/by-nc-nd/4.0/",target:"_blank",rel:"noreferrer"},"CC BY-NC-ND 4.0"),t(" に従うライセンスで公開しています.")],-1),p=e("p",null,"教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.",-1),m=e("p",null,[e("img",{src:_,alt:"cc_by_nc_nd"})],-1);function f(h,u,b,g,v,N){const a=s;return o(),c("div",null,[l,r(a,{readTime:"1",words:"62"}),i,p,m])}const B=n(d,[["render",f]]);export{w as __pageData,B as default}; diff --git a/assets/development_aws_license.md.5f519b50.lean.js b/assets/development_aws_license.md.38e84b81.lean.js similarity index 95% rename from assets/development_aws_license.md.5f519b50.lean.js rename to assets/development_aws_license.md.38e84b81.lean.js index bb328c67..1b1f04cd 100644 --- a/assets/development_aws_license.md.5f519b50.lean.js +++ b/assets/development_aws_license.md.38e84b81.lean.js @@ -1 +1 @@ -import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o,c,H as r,k as e,a as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const _="/assets/cc_by_nc_nd.c97a96cd.png",w=JSON.parse('{"title":"ライセンス","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/license.md","filePath":"development/aws/license.md","lastUpdated":1695377563000}'),d={name:"development/aws/license.md"},l=e("h1",{id:"ライセンス",tabindex:"-1"},[t("ライセンス "),e("a",{class:"header-anchor",href:"#ライセンス","aria-label":'Permalink to "ライセンス"'},"​")],-1),i=e("p",null,[t("本教科書およびハンズオンのソースコードは "),e("a",{href:"https://creativecommons.org/licenses/by-nc-nd/4.0/",target:"_blank",rel:"noreferrer"},"CC BY-NC-ND 4.0"),t(" に従うライセンスで公開しています.")],-1),p=e("p",null,"教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.",-1),m=e("p",null,[e("img",{src:_,alt:"cc_by_nc_nd"})],-1);function f(h,u,b,g,v,N){const a=s;return o(),c("div",null,[l,r(a,{readTime:"1",words:"62"}),i,p,m])}const B=n(d,[["render",f]]);export{w as __pageData,B as default}; +import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o,c,H as r,k as e,a as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const _="/assets/cc_by_nc_nd.c97a96cd.png",w=JSON.parse('{"title":"ライセンス","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/license.md","filePath":"development/aws/license.md","lastUpdated":1699051935000}'),d={name:"development/aws/license.md"},l=e("h1",{id:"ライセンス",tabindex:"-1"},[t("ライセンス "),e("a",{class:"header-anchor",href:"#ライセンス","aria-label":'Permalink to "ライセンス"'},"​")],-1),i=e("p",null,[t("本教科書およびハンズオンのソースコードは "),e("a",{href:"https://creativecommons.org/licenses/by-nc-nd/4.0/",target:"_blank",rel:"noreferrer"},"CC BY-NC-ND 4.0"),t(" に従うライセンスで公開しています.")],-1),p=e("p",null,"教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.",-1),m=e("p",null,[e("img",{src:_,alt:"cc_by_nc_nd"})],-1);function f(h,u,b,g,v,N){const a=s;return o(),c("div",null,[l,r(a,{readTime:"1",words:"62"}),i,p,m])}const B=n(d,[["render",f]]);export{w as __pageData,B as default}; diff --git a/assets/development_aws_main.md.587d14dd.js b/assets/development_aws_main.md.587d14dd.js new file mode 100644 index 00000000..dad08245 --- /dev/null +++ b/assets/development_aws_main.md.587d14dd.js @@ -0,0 +1,1911 @@ +import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o}from"./chunks/earth_from_earth.8c108f53.js";import{_ as e,a as t,b as r,c}from"./chunks/terminal.94539704.js";import{_ as i,a as y,b as d,c as u,d as A,e as C,f as b,g as m,h as F,i as D,j as h}from"./chunks/iac.2263bc12.js";import{_ as s,a}from"./chunks/VPC.e1acca4d.js";import{_ as g,a as B,b as E,c as _,d as k,e as v,f}from"./chunks/ec2_keypair_console.fc89ef69.js";import{_ as q,a as S}from"./chunks/cnn.a8836fd9.js";import{_ as w,a as P,b as I,c as x,d as T,e as W,f as $,g as L,h as G,i as N,j as U,k as R,l as X,m as M,n as H,o as z,p as O}from"./chunks/mnist_prediction.4ba5b405.js";import{_ as j,a as V,b as K,c as Y,d as J,e as Q,f as Z,g as ss}from"./chunks/ecs.73d77e6a.js";import{_ as as,a as ns,b as ps,c as ls,d as os,e as es,f as ts,g as rs,h as cs,i as is,j as ys}from"./chunks/ask_many_output.0bb19110.js";import{_ as ds,a as us,b as As,c as Cs,d as bs,e as ms,f as Fs,g as Ds,h as hs,i as gs,j as Bs,k as Es,l as _s,m as ks,n as vs,o as fs,p as qs,q as Ss,r as ws,s as Ps}from"./chunks/cloud_development.e43e5d4a.js";import{_ as Is,a as xs}from"./chunks/rest_api.602a6e96.js";import{_ as Ts,a as Ws,b as $s,c as Ls,d as Gs}from"./chunks/s3_vs_filesystem.fd65005d.js";import{_ as Ns,a as Us,b as Rs,c as Xs,d as Ms,e as Hs,f as zs,g as Os,h as js,i as Vs,j as Ks,k as Ys,l as Js}from"./chunks/s3_bucket_filelist.89f3f384.js";import{_ as Qs,a as Zs,b as sa,c as aa,d as na,e as pa,f as la,g as oa,h as ea}from"./chunks/bashoutter_2.cd8a2a95.js";import{_ as ta,a as ra,b as ca,c as ia,d as ya,e as da,f as ua,g as Aa,h as Ca,i as ba,j as ma,k as Fa,l as Da,m as ha,n as ga,o as Ba}from"./chunks/venv_shell.dc2530bc.js";import{_ as Ea,o as _a,c as ka,H as va,k as n,a as fa,Q as qa}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const pn=JSON.parse('{"title":"はじめに!","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/main.md","filePath":"development/aws/main.md","lastUpdated":1699051935000}'),Sa={name:"development/aws/main.md"},wa=n("h1",{id:"はじめに",tabindex:"-1"},[fa("はじめに! "),n("a",{class:"header-anchor",href:"#はじめに","aria-label":'Permalink to "はじめに!"'},"​")],-1),Pa=qa('

    本書の目的・内容

    本書は,東京大学計数工学科で 2021 年度 S1/S2 タームに開講されている"システム情報工学特論"の講義資料として作成された.

    本書の目的は,クラウドの初心者を対象とし,クラウドの基礎的な知識・概念を解説する. また, Amazon Web Services (以下, AWS) の提供するクラウド環境を実例として,具体的なクラウドの利用方法をハンズオンを通して学ぶ.

    とくに,科学・エンジニアリングの学生を対象として,研究などの目的でクラウドを利用するための実践的な手順を紹介する. 知識・理論の説明は最小限に留め,実践を行う中で必要な概念の解説を行う予定である. 読者が今後,研究などでクラウドを利用する際の,足がかりとなれば本書の目的は十分達成されたことになる.

    本書は以下のような三部構成になっている.

    本書の構成
    テーマハンズオン

    第一部 (1章-4章)

    クラウドの基礎

    • AWSに自分のサーバーを立ち上げる

    第二部 (5章-9章)

    クラウドを活用した機械学習

    • AWS と Jupyter を使って始めるディープラーニング

    • スケーラブルな自動質問回答ボットを作る

    • 並列化されたハイパーパラメータサーチの実装

    第三部 (10章-13章)

    サーバーレスアーキテクチャ入門

    • Lambda, DynamoDB, S3 の演習

    • 俳句を投稿する SNS "Bashoutter" を作る

    第一部は,クラウドの基礎となる概念・知識を解説する. セキュリティやネットワークなど,クラウドを利用する上で最低限おさえなければいけないポイントを説明する. ハンズオンでは,はじめての仮想サーバーを AWS に立ち上げる演習を行う.

    第二部では,クラウド上で科学計算 (とくに機械学習) を走らせるための入門となる知識・技術を解説する. あわせて, Docker とよばれる仮想計算環境の使用方法を紹介する. 一つ目のハンズオンでは, AWS のクラウドで Jupyter Notebook を起動し簡単な機械学習の計算を走らせる課題を実践する. 二つ目のハンズオンでは,深層学習を用いた自然言語処理により,質問に自動で回答を生成するボットを作成する. 最後に,複数台の GPU インスタンスからなるクラスターを起動し,並列に深層学習のハイパーパラメータサーチを行う方法を紹介する.

    第三部では,サーバーレスアーキテクチャとよばれる最新のクラウドのアーキテクチャを紹介する. これは,サーバーの処理能力を負荷に応じてより柔軟に拡大・縮小するための概念であり,それ以前 (Serverful としばしばよばれる) と質的に異なる設計思想をクラウドに導入するものである. ハンズオンでは,サーバーレスクラウドの主要なコンポーネントである Lambda, DynamoDB, S3 の演習を提供する. さらに,サーバーレスの技術を使用して簡単な SNS をクラウド上に作成する.

    これらの豊富なハンズオンにより, AWS 上にクラウドシステムを開発するための知識と技術が身につくはずである. いずれのハンズオンも,実用性を重視したものになっており,これらをベースにカスタマイズを施すことで様々な応用が可能である.

    本書のフィロソフィー

    本書のフィロソフィーを一言で表すなら, "ロケットで宇宙まで飛んでいって一度地球を眺めてみよう!" である.

    どういうことか?

    ここでいう"地球"とは,クラウドコンピューティングの全体像のことである. 言うまでもなく,クラウドという技術は非常に広範かつ複雑な概念で,幾多の情報技術・ハードウェア・アルゴリズムが精緻に組み合わさってできた総体である. そして,今日では科学研究から日常のインフラ設備に至るまで,我々の社会の多くの部分がクラウド技術によって支えられている.

    ここでいう"ロケット"とはこの講義のことである. この講義では,ロケットに乗って宇宙まで飛び立ち,地球(クラウド)の全体を自身の目で眺めてもらう. その際,ロケットの成り立ちや仕組み (背後にある要素技術やプログラムのソースコード) を深くは問わない. 将来,自分が研究などの目的でクラウドを利用することになった際に,改めて学んでもらえば良い. 本書の目的はむしろ,クラウドの最先端に実際に触れ,そこからどんな景色が見えるか(どんな応用が可能か)を実感してもらうことである.

    そのような理由で,本書はクラウドの基礎から応用まで幅広いテーマを取り扱う. 第一部はクラウドの基礎から始め,第二部では一気にレベルアップし機械学習(深層学習)をクラウドで実行する手法を解説する. さらに第三部では,サーバーレス・アーキテクチャというここ数年のうちに確立した全く新しいクラウドの設計について解説する. それぞれで本一冊分以上の内容に相当するものであるが,本書はあえてこれらを一冊にまとめ連続的に俯瞰するという野心的な意図をもって執筆された.

    決して楽な搭乗体験ではないかもしれないが,このロケットにしがみついてきてもらえれば,とてもエキサイティングな景色が見られることを約束したい.

    宇宙からみた地球 (Image from NASA https://www.nasa.gov/image-feature/planet-of-clouds)

    AWS アカウント

    本書では,ハンズオン形式で AWS のクラウドを実際に動かす演習を提供する. 自分でハンズオンを実行してみたい読者は,各自で AWS のアカウントの作成をしていただく. AWS のアカウントの作成の仕方は巻末付録 (AWS アカウントの取得) に簡単に記載したので,必要に応じて参照していただきたい.

    AWS にはいくつかの機能に対して無料利用枠が設定されており,いくつかのハンズオンは無料の範囲内で実行できる. 一方,ほかのハンズオン (とくに機械学習を扱うもの) では数ドル程度のコストが発生する. ハンズオンごとに発生するおおよそのコストについて記述があるので,注意をしながらハンズオンに取り組んでいただきたい.

    また,大学などの教育機関における講義で AWS を使用する際は, AWS Educate というプログラムを利用することも可能である. これは,講義の担当者が申請を行うことで,受講する学生に対し AWS クレジットが提供されるというプログラムである. AWS Educate を利用することで金銭的な負担なしに AWS を体験することができる. また,講義を経由せず個人でも AWS Educate に参加することも可能である. AWS Educate からは様々な学習教材が提供されているので,ぜひ活用してもらいたい.

    環境構築

    本書では, AWS 上にクラウドアプリケーションを展開するハンズオンを実施する. そこで紹介するプログラムを実行するためには,以下の計算機環境が必要である. インストールの方法については,巻末付録 (Appendix: 環境構築) に記してある. 必要に応じて参照し,環境構築を各自実施していただきたい.

    • UNIX 系コンソール: ハンズオンで紹介するコマンドを実行したり, SSH でサーバーにアクセスするため, UNIX 系のコンソール環境が必要である. Mac または Linux のユーザーは, OS に標準搭載のコンソール(ターミナルとも呼ばれる)を使用すればよい. Windows のユーザーは, Windows Subsystem for Linux (WSL) を使い, Linux の仮想環境のインストールを推奨する (WSL のインストール 参照).

    • Docker: 本書では Docker とよばれる仮想計算環境の利用方法を解説する. インストール手順については Docker のインストール を参照のこと.

    • Python: Version 3.6 以上をインストールする. とくに,ハンズオンでは venv モジュールを使用する. venv の使い方は Python クイックガイド 参照のこと.

    • Node.js: version 12.0 以上 をインストールする.

    • AWS CLI: Version 2 をインストールする. インストール手順については AWS CLI のインストール 参照のこと.

    • AWS CDK: Version 1.100 以上をインストールする. Version 2 以降には未対応である. インストール手順については AWS CDK のインストール 参照のこと.

    • AWS 認証鍵の設定: AWS API をコマンドラインから呼ぶには,認証鍵 (secret key) が設定されている必要がある. 認証鍵の設定については AWS CLI のインストール 参照のこと.

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は ハンズオン実行用の Docker image の使い方 に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    • Python の基本的な理解: 本書では Python を使ってプログラムの作成を行う. 使用するライブラリは十分抽象化されており,関数の名前を見ただけで意味が明瞭なものがほとんどであるので, Python に詳しくなくても心配する必要はない.

    • Linux コマンドラインの基礎的な理解: クラウドを利用する際,クラウド上に立ち上がるサーバーは基本的に Linux である. Linux のコマンドラインについて知識があると,トラブルシュートなどが容易になる. 筆者のおすすめの参考書は The Linux Command Line by William Shotts である. ウェブで無料で読むことができるので,読んだことのない人はぜひ一読を.

    講義に関連する資料

    ハンズオンで使うプログラムや教科書のソースコードは以下のウェブページで公開している.

    https://github.com/tomomano/learn-aws-by-coding

    本書で使用するノーテーションなど

    • コードやシェルのコマンドは monospace letter で記述する.

    • シェルに入力するコマンドは,それがシェルコマンドであると明示する目的で,先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力には $ はついていない点に留意する.

    また,以下のような形式で注意やチップスを提供する.

    追加のコメントなどを記す.

    発展的な議論やアイディアなどを紹介する.

    陥りやすいミスなどの注意事項を述べる.

    絶対に犯してはならないミスを指摘する.

    クラウド概論

    クラウドとは?

    Cloud

    クラウドとはなにか? クラウドという言葉は,それ自身がとても広い意味をもつので,厳密な定義付けを行うことは難しい.

    学術的な意味でのクラウドの定義づけをするとしたら,NIST(米国・国立標準技術研究所) による The NIST Definition of Cloud Computing が引用されることが多い. ここに記載されたクラウドの定義・モデルを図示したのが figure_title である.

    The NIST Definition of Cloud Computing

    これによると,クラウドとは以下の要件が満たされたハードウェア/ソフトウェアの総体のことをいう.

    • On-demand self-service 利用者のリクエストに応じて計算資源が自動的に割り当てられる.

    • Broad network access 利用者はネットワークを通じてクラウドにアクセスできる.

    • Resource pooling クラウドプロバイダーは,所有する計算資源を分割することで複数の利用者に計算資源を割り当てる.

    • Rapid elasticity 利用者のリクエストに応じて,迅速に計算資源の拡大あるいは縮小を行うことができる.

    • Measured service 計算資源の利用量を計測・監視することができる.

    …と,いわれても抽象的でよくわからないかもしれない.もう少し具体的な話をする.

    個人が所有する計算機で, CPU をアップグレードしようと思ったら,物理的に筐体を開け,CPU ソケットを露出させ,新しい CPU に交換する必要があるだろう. あるいは,ストレージがいっぱいになってしまったら,古いディスクを抜き取り,新しいディスクを挿入する必要がある. 計算機の場所を移動させたときには,新しい部屋の LAN ケーブルを差し込まないとネットワークには接続できない.

    クラウドでは,これらの操作がプログラムからのコマンドによって実行できる. CPU が 1000 個欲しいと思ったならば,そのようにクラウドプロバイダーにリクエストを送れば良い. すると,数分もしないうちに 1000 CPU の計算資源が割り当てられる. ストレージを 1TB から 10TB に拡張しようと思ったならば,そのようにコマンドを送ればよい (これは,Google Drive や Dropbox などのサービスなどで馴染みのある人も多いだろう). 計算資源を使い終わったら,そのことをプロバイダーに伝えれば,割り当て分はすぐさま削除される. クラウドプロバイダーは,使った計算資源の量を正確にモニタリングしており,その量をもとに利用料金の計算が行われる.

    このように,クラウドの本質は物理的なハードウェアの仮想化・抽象化であり,利用者はコマンドを通じて,まるでソフトウェアの一部かのように,物理的なハードウェアの管理・運用を行うことができる. もちろん,背後では,データセンターに置かれた膨大な数の計算機が大量の電力を消費しながら稼働している. クラウドプロバイダーはデータセンターの計算資源を上手にやりくりし,ソフトウェアとしてのインターフェースをユーザーに提供することで,このような仮想化・抽象化を達成しているわけである. クラウドプロバイダーの視点からすると,大勢のユーザーに計算機を貸し出し,データセンターの稼働率を常時 100%に近づけることで,利益率の最大化を図っているのである.

    著者の言葉で,クラウドの重要な特性を定義するならば,以下のようになる.

    クラウドとは計算機ハードウェアの抽象化である.つまり,物理的なハードウェアをソフトウェアの一部かのように自在に操作・拡大・接続することを可能にする技術である.

    先述の The NIST Definition of Cloud Computing に戻ると,クラウドプロバイダーによるクラウドサービスの形態としては,次の三つが定義されている (figure_title).

    • Software as a Service (SaaS): クラウド上で実行されるアプリケーションをサービスとして利用者に提供する形態. 例として, Google Drive や Slack などが挙げられる. 利用者は,背後にあるクラウドのインフラ (ネットワークやサーバーなど) には直接触れず,アプリケーションとして提供されているクラウドサービスを享受する.

    • Platform as a Service (PaaS): 顧客の作成したアプリケーション (多くの場合データベースと API リクエスト処理を行うサーバーのコードから構成される) をデプロイする環境をサービスとして利用者に提供する形態. PaaS では利用者はクラウドのインフラに直接触れることはなく,計算負荷が増減した際のサーバーのスケーリングはクラウドプロバイダーによってなされる. 例としては, Google App Engine や Heroku などがある.

    • Infrastructure as a Service (IaaS): クラウド上の計算インフラストラクチャーを従量課金制で利用者に提供する形態. 利用者は必要なネットワーク・サーバー・ストレージをプロバイダーから借り受け,そこに自身のアプリケーションを展開し運用する. IaaS の例としては AWS EC2 などが挙げられる.

    本書が扱うのは,主に IaaS におけるクラウド開発である. すなわち,開発者がクラウドのインフラを直接操作し,所望のネットワーク・サーバー・ストレージなどを一から構成し,そこにアプリケーションを展開するというクラウド開発である. この意味において,クラウドの開発とはクラウドインフラストラクチャーを定義・展開するプログラムを構築するステップインフラ上で実際に走るアプリケーションを作成するステップの二つに分けることができる. この二つは,プログラマーの技術としてはある程度分業を行うことが可能であるが,最も効率化・最適化されたクラウドシステムを構築するためには両方の理解が必須である. 本書では,前者 (クラウドインフラの記述) に重きを置きつつ,アプリケーションレイヤーの話題も取り扱う. PaaS とは,開発者はアプリケーションレイヤーの開発に注力し,クラウドインフラの部分はクラウドプロバイダーに依存するという概念である. PaaS は,クラウドインフラの開発が不要になることで開発の時間が短縮されるが,細かなインフラの挙動はコントロールできないという限界がある. 本書では PaaS についてはとくに取り扱わない.

    SaaS は本書の文脈では開発による"成果物"と捉えられるだろう. すなわち, IaaS を構成するプログラムを作成し展開することによって,一般の人が利用できるようなウェブ上の計算サービスやデータベースを提供することが開発の最終ゴールである. 本書のハンズオンではその実例として,シンプルな SNS の作成 (Hands-on #6: Bashoutter) などの演習を提供する.

    なお,最近では Function as a Service (FaaS) やサーバーレスコンピューティングなども新たなクラウドのカテゴリとして認知されている. これらの概念については Hands-on #5: サーバーレス入門 などの章で詳しく触れていく. 本書を読み進める中で明らかになるように,クラウドの技術は日進月歩である. 本書では実用的・教育的な観点から,従来的なクラウドの設計概念に触れたあと,サーバーレスなどの最新の技術も網羅するので,楽しみにしながら読み進めていただきたい.

    最後に,The NIST Definition of Cloud Computing によると,クラウドの運用形態について次のような定義がなされている (figure_title). 特定の組織・団体・企業の内部のみで使用されるクラウドを,プライベートクラウド (private cloud) とよぶ. 例えば,大学や研究機関では,その機関の構成員向けの大規模計算機サーバーが運用されていることが多い. プライベートクラウドは,組織の構成員ならば無料もしくは極めて割安のコストで計算を実行できる. しかし,使用できる計算資源の上限は限られる場合が多く,拡張時の柔軟性に欠ける場合もある.

    一方,商用のサービスとして一般の顧客に向けたクラウドのことを,パブリッククラウド (public cloud) とよぶ. 有名なパブリッククラウドプラットフォームの例を挙げると, Google 社が提供する Google Cloud Platform (GCP), Microsoft 社が提供する Azure, Amazon 社が提供する Amazon Web Services (AWS) などがある. パブリッククラウドを利用する場合は,プロバイダーの設定した利用料金を支払うことになる. その分,巨大なデータセンターを運用する企業の計算資源にアクセスすることができるので,計算のキャパシティは無尽蔵にあるといって過言でない.

    第三のクラウドの運用形態として,コミュニティクラウド (community cloud) が挙げられる. これは,例えば政府の省庁・機関など目的・役割を共有する団体・組織が共有して運用するクラウドを指す. 最後に,ハイブリッドクラウド (hybrid cloud) という形態もあり,これはプライベート・パブリック・コミュニティクラウドの二つ以上の組み合わせによって構成されるクラウドのことである. データ保護の観点から,いくつかの機密データやプライバシーに関わる情報はプライベートクラウドに保持し,残りのシステムをパブリッククラウドに依存する,などの形態が想定される.

    本書で説明するのは,基本的にパブリッククラウドを使ったクラウド開発である. 特に,Amazon Web Services (AWS) を使用して,具体的な技術と概念を学んでいく. 一方で,サーバーのスケーリングや仮想計算環境などのテクニックはすべてのクラウドに共通な概念であるので,クラウドのプラットフォームが変わろうと一般に通用する知識も同時に身につくはずだ.

    なぜクラウドを使うのか?

    上述のように,クラウドとはプログラムを通じて自由に計算資源を操作することのできる計算環境である. ここでは,リアルなローカル計算環境と比べて,なぜクラウドを使うと良いことがあるのかについて述べたい.

    1. 自由にサーバーのサイズをスケールできる

      なにか新しいプロジェクトを始めるとき,あらかじめ必要なサーバーのスペックを知るのは難しい. いきなり大きなサーバーを買うのはリスクが高い. 一方で,小さすぎるサーバーでは,後のアップグレードが面倒である. クラウドを利用すれば,プロジェクトを進めながら,必要な分だけの計算資源を確保することができる. 2. 自分でサーバーをメンテナンスする必要がない

      悲しいことに,コンピュータとは古くなるものである.最近の技術の進歩の速度からすると,5 年も経てば,もはや当時の最新コンピュータも化石と同じである. 5 年ごとにサーバーを入れ替えるのは相当な手間である. またサーバーの停電や故障など不意の障害への対応も必要である. クラウドでは,そのようなインフラの整備やメンテナンスはプロバイダーが自動でやってくれるので,ユーザーが心配する必要がない. 3. 初期コスト 0

      自前の計算環境とクラウドの,経済的なコストのイメージを示したのが figure_title である. クラウドを利用する場合の初期コストは基本的に 0 である. その後,使った利用量に応じてコストが増大していく. 一方,自前の計算環境では,大きな初期コストが生じる. その分,初期投資後のコストの増加は,電気利用料やサーバー維持費などに留まるため,クラウドを利用した場合よりも傾きは小さくなる. 自前の計算機では,ある一定期間後,サーバーのアップグレードなどによる支出が生じることがある. 一方,クラウドを利用する場合は,そのような非連続なコストの増大は基本的に生じない. クラウドのコストのカーブが,自前計算環境のコストのカーブの下にある範囲においては,クラウドを使うことは経済的なコスト削減につながる.

      クラウドと自前計算機環境の経済的コストの比較

    とくに,**1.**の点は研究の場面では重要であると筆者は感じる. 研究をやっていて,四六時中計算を走らせ続けるという場合は少ない. むしろ,新しいアルゴリズムが完成したとき・新しいデータが届いたとき,集中的・突発的に計算タスクが増大することが多いだろう. そういったときに,フレキシブルに計算力を増強させることができるのは,クラウドを使う大きなメリットである.

    ここまでクラウドを使うメリットを述べたが,逆に,デメリットというのも当然存在する.

    1. クラウドは賢く使わないといけない

      figure_title で示したコストのカーブにあるとおり,使い方によっては自前の計算環境のほうがコスト的に有利な場面は存在しうる. クラウドを利用する際は,使い終わった計算資源はすぐに削除するなど,利用者が賢く管理を行う必要があり,これを怠ると思いもしない額の請求が届く可能性がある. 2. セキュリティ

      クラウドは,インターネットを通じて世界のどこからでもアクセスできる状態にあり,セキュリティ管理を怠ると簡単にハッキングの対象となりうる. ハッキングを受けると,情報流出だけでなく,経済的な損失を被る可能性がある. 3. ラーニングカーブ

      上記のように,コスト・セキュリティなど,クラウドを利用する際に留意しなければならない点は多い. 賢くクラウドを使うには,十分なクラウドの理解が必要であり,そのラーニングカーブを乗り越える必要がある.

    Mac/Linux などでコマンドを入力するときに使用する,あの黒い画面のことを Terminal とよんだりする. この言葉の語源をご存知だろうか?

    Terminal

    この言葉の語源は,コンピュータが誕生して間もない頃の時代に遡る. その頃のコンピュータというと,何千何万のという数の真空管が接続された,会議室一個分くらいのサイズのマシンであった. そのような高価でメンテが大変な機材であるから,当然みんなでシェアして使うことが前提となる. ユーザーがコンピュータにアクセスするため,マシンからは何本かのケーブルが伸び,それぞれにキーボードとスクリーンが接続されていた… これを Terminal とよんでいたのである. 人々は,代わる代わる Terminal の前に座って,計算機との対話を行っていた.

    時代は流れ,Windows や Mac などのいわゆるパーソナルコンピュータの出現により,コンピュータはみんなで共有するものではなく,個人が所有するものになった.

    最近のクラウドの台頭は,みんなで大きなコンピュータをシェアするという,最初のコンピュータの使われ方に原点回帰していると捉えることもできる. 一方で,スマートフォンやウェアラブルなどのエッジデバイスの普及も盛んであり,個人が複数の"小さな"コンピュータを所有する,という流れも同時に進行しているのである.

    AWS 入門

    AWS とは?

    本書では,クラウドの実践を行うプラットフォームとして, AWS を用いる. 実践にあたって,最低限必要な AWS の知識を本章では解説しよう.

    AWS (Amazon Web Services) は Amazon 社が提供する総合的なクラウドプラットフォームである. AWS は Amazon 社が持つ膨大な計算リソースを貸し出すクラウドサービスとして,2006 年に誕生した. 2021 年では,クラウドプロバイダーとして最大のマーケットシェア (約 32%) を保持している (参照). Netflix や Slack をはじめとした多くのウェブ関連のサービスで,一部または全てのサーバーリソースが AWS から提供されているとのことである. よって,知らないうちに AWS の恩恵にあずかっている人も少なくないはずだ.

    最大のシェアをもつだけに,機能・サービスの幅広さはほかのクラウドプラットフォームと比べ抜きんでている. また,利用者数が多いことを反映して,公式あるいはサードパーティによる技術紹介記事が数多くウェブ上に存在しているだけでなく,ライブラリのユーザーコミュニティも大きく問題解決が捗るのも魅力の一つだ. 初期のころウェブビジネスを行う企業がユーザーの大半を占めていたが,最近は大学などでの科学研究用途としても頻繁に用いられるようになってきている.

    AWS の機能・サービス

    figure_title は,執筆時点において AWS で提供されている主要な機能・サービスの一覧である.

    AWSで提供されている主要なサービス一覧

    計算,ストレージ,データベース,ネットワーク,セキュリティなど,クラウドの構築に必要な様々な要素が独立したコンポーネントとして提供されている. 基本的に,これらを組み合わせることで一つのクラウドシステムができあがる.

    また,機械学習・音声認識・AR/VR など,特定のアプリケーションにパッケージ済みのサービスも提供されている. これらを合計すると全部で 170 個以上のサービスが提供されているとのことである (参照).

    AWS の初心者が陥りがちなのは,大量のサービスの数に圧倒され,どこから手をつけたらよいのかわからなくなる,という状況である. たくさんのサービスの中から,どのサービスをどの順番で学んでいったらいいのか,その道筋すら明らかでなく,大きな参入障壁となっていることは間違いない. だが実のところ, AWS の基本的な構成要素はそのうちの数個のみに限られる. 基本要素となる機能の使い方を知れば, AWS のおおよそのリソースを使いこなすことが可能になる. ほかの機能の多くは,基本の要素を組み合わせて特定のアプリケーションに特化したパッケージとして AWS が用意したものである. そのポイントを認知することが, AWS の学習の最初のステップである.

    ここでは, AWS 上でクラウドシステムを構築するときの基本となる構成要素を列挙する. これらは後のハンズオンで実際にプログラムを書きながら体験する. 現時点では,名前だけでも頭の片隅に記憶してもらえればよい.

    計算

    S3 EC2 (Elastic Compute Cloud) 様々なスペックの仮想マシンを作成し,計算を実行することができる. クラウドの最も基本となる構成要素である. Hands-on #1: 初めての EC2 インスタンスを起動する, Hands-on #2: AWS でディープラーニングを実践, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で詳しく触れる.

    S3 Lambda Function as a Service (FaaS) とよばれる,小さな計算をサーバーなしで実行するためのサービス. サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    ストレージ

    S3 EBS (Elastic Block Store) EC2 に付与することのできる仮想データドライブ. いわゆる"普通の"(一般的な OS で使われている)ファイルシステムを思い浮かべてくれたらよい.

    S3 S3 (Simple Storage Service) Object Storage とよばれる,API を使ってデータの読み書きを行う,いうなれば”クラウド・ネイティブ”なデータの格納システムである. サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    データベース

    S3 DynamoDB NoSQL 型のデータベースサービス (知っている人は mongoDB などを思い浮かべたらよい). サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    ネットワーク

    S3 VPC(Virtual Private Cloud) AWS 上に仮想ネットワーク環境を作成し,仮想サーバー間の接続を定義したり,外部からのアクセスなどを管理する. EC2 は VPC の内部に配置されなければならない.

    API Gateway S3 API のエンドポイントとバックエンドのサービス (Lambda など) を接続する際に用いる,リバースプロキシとしての役割を担う. Hands-on #6: Bashoutter で詳しく解説する.

    Region と Availability Zone

    AWS を使用する際に知っておかなければならない重要な概念として, リージョン (Region)Availability Zone (AZ) がある (figure_title). 以下ではこの概念について簡単に記述する.

    AWSにおける Region と Availability Zones

    リージョン (Region) とは,おおまかに言うとデータセンターの所在地のことである. 執筆時点において, AWS は世界の 25 の国と地域でデータセンターを所有している. figure_title は執筆時点で利用できるリージョンの世界地図を示している. 日本では東京と大阪にデータセンターがある. 各リージョンには固有の ID がついており,例えば東京は ap-northeast-1, 米国オハイオ州は us-east-2,などと定義されている.

    Regions in AWS(出典: https://aws.amazon.com/about-aws/global-infrastructure/)

    AWS コンソールにログインすると,画面右上のメニューバーでリージョンを選択することができる(figure_title, 赤丸で囲った箇所). EC2, S3 などの AWS のリソースは,リージョンごとに完全に独立である. したがって,リソースを新たにデプロイする際,あるいはデプロイ済みのリソースを閲覧する際は,コンソールのリージョンが正しく設定されているか,確認する必要がある. ウェブビジネスを展開する場合などは,世界の各地にクラウドを展開する必要があるが,個人的な研究用途として用いる場合は,最寄りのリージョン (i.e. 東京) を使えば基本的に問題ない.

    AWSコンソールでリージョンを選択

    Avaialibity Zone (AZ) とは,リージョン内で地理的に隔離されたデータセンターのことである. それぞれのリージョンは 2 個以上の AZ を有しており,もし一つの AZ で火災や停電などが起きた場合でも,ほかの AZ がその障害をカバーすることができる. また, AZ 間は高速な AWS 専用ネットワーク回線で結ばれているため, AZ 間のデータ転送は極めて早い. AZ は,ビジネスなどでサーバーダウンが許容されない場合などに注意すべき概念であり,個人的な用途で使う限りにおいてはあまり深く考慮する必要はない.言葉の意味だけ知っておけば十分である.

    AWS を使用する際,どこのリージョンを指定するのがよいのだろうか? インターネットの接続速度の観点からは,地理的に一番近いリージョンを使用するのが一般的によいだろう. 一方, EC2 の利用料などはリージョンごとに価格設定が若干 (10-20%程度) 異なる. したがって,自分が最も頻繁に利用するサービスの価格が最も安く設定されているリージョンを選択する,というのも重要な視点である. また,いくつかのサービスは,特定のリージョンで利用できない場合もある. これらのポイントから総合的に判断して使用するリージョンを決めると良い.

    AWS Educate を利用している読者へ

    執筆時点において,AWS Educate による Starter Account を使用している場合は us-east-1 region のみ利用できる (参照).

    AWS でのクラウド開発

    AWS のクラウドの全体像がわかってきたところで,次のトピックとして,どのようにして AWS 上にクラウドの開発を行い,展開していくかについての概略を解説しよう.

    AWS のリソースを追加・編集・削除するなどの操作を実行するには,コンソールを用いる方法と,API を用いる方法の,二つの経路がある.

    コンソール画面からリソースを操作する

    AWS のアカウントにログインすると,まず最初に表示されるのがAWS コンソールである (figure_title).

    AWSマネージメントコンソール画面

    コンソールを使うことで, EC2 のインスタンスを立ち上げたり,S3 のデータを追加・削除したり,ログを閲覧したりなど,AWS 上のあらゆるリソースの操作を GUI (Graphical User Interface) を通して実行することができる. 初めて触る機能をポチポチと試したり,デバッグを行うときなどにとても便利である

    コンソールはさらっと機能を試したり,開発中のクラウドのデバッグをするときには便利なのであるが,実際にクラウドの開発をする場面でこれを直接いじることはあまりない. むしろ,次に紹介する API を使用して,プログラムとしてクラウドのリソースを記述することで開発を行うのが一般的である. そのような理由で,本書では AWS コンソールを使った AWS の使い方はあまり触れない. AWS のドキュメンテーションには,たくさんの チュートリアル が用意されており,コンソール画面から様々な操作を行う方法が記述されているので,興味がある読者はそちらを参照されたい.

    API からリソースを操作する

    API (Application Programming Interface) を使うことで,コマンドを AWS に送信し,クラウドのリソースの操作をすることができる. API とは,端的に言えば AWS が公開しているコマンドの一覧であり,GET, POST, DELETE などの REST API から構成されている (REST API については REST API で簡単に解説する). が,直接 REST API を入力するのは面倒であるので,その手間を解消するための様々なツールが提供されている.

    例えば, AWS CLI は, UNIX コンソールから AWS API を実行するための CLI (Command Line Interface) である. CLI に加えて,いろいろなプログラミング言語での SDK (Software Development Kit) が提供されている.以下に一例を挙げる.

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    python
    import boto3
    +
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    +
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン (Hands-on #1: 初めての EC2 インスタンスを起動する) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    python
    import boto3
    +
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)
    import boto3
    +
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    AWS CLI のインストールについては, AWS CLI のインストール を参照.

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは AWS CLI のインストール を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://\${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://\${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    sh
    $ aws s3 ls
    +
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    +
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    sh
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://\${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://\${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    sh
    $ aws s3 ls "s3://\${bucketName}" --human-readable
    +
    +2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://\${bucketName}" --human-readable
    +
    +2020-06-07 23:54:19   13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    sh
    $ aws s3 rb "s3://\${bucketName}" --force
    $ aws s3 rb "s3://\${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    AWS 上のあらゆるリソースには, Amazon Resource Name (ARN) という固有の ID が付与されている. ARN は arn:aws:s3:::my_bucket/ のようなフォーマットで記述され,ARN を使用することで,特定の AWS リソース (S3 のバケットや EC2 のインスタンス) を一意的に参照することができる.

    S3 バケットや EC2 インスタンスなどには ARN に加えて,人間が読みやすい名前を定義することも可能である. この場合は,ARN または名前のどちらを用いても同じリソースを参照することが可能である.

    CloudFormation と AWS CDK

    CloudFormation による Infrastructure as Code (IaC)

    前節で述べたように,AWS API を使うことでクラウドのあらゆるリソースの作成・管理が可能である. よって,原理上は, API のコマンドを組み合わせていくことで,自分の作りたいクラウドを設計することができる.

    しかし,ここで実用上考慮しなければならない点が一つある. AWS API には大きく分けて,リソースを操作するコマンドと,タスクを実行するコマンドがあることである (figure_title).

    AWS APIはリソースを操作するコマンドとタスクを実行するコマンドに大きく分けられる.リソースを記述・管理するのに使われるのが, CloudFormation と CDK である.

    リソースを操作するとは,EC2 のインスタンスを起動したり,S3 のバケットを作成したり,データベースに新たなテーブルを追加する,などの静的なリソースを準備する 操作を指す. "ハコ"を作る操作とよんでも良いだろう. このようなコマンドは,クラウドのデプロイ時にのみ,一度だけ実行されればよい

    タスクを実行するコマンド とは, EC2 のインスタンスにジョブを投入したり, S3 のバケットにデータを読み書きするなどの操作を指す. これは, EC2 や S3 などのリソース ("ハコ") を前提として,その内部で実行されるべき計算を記述するものである. 前者に比べてこちらは動的な操作を担当する,と捉えることもできる.

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    json
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\\n",
    +                     "yum update -y aws-cfn-bootstrap\\n",
    +
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\\n",
    +
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\\n",
    +                     "yum update -y aws-cfn-bootstrap\\n",
    +
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\\n",
    +
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    python
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
    +
    +class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
    +
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
    +
    +class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
    +
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

    • AWS CDK Examples: CDK を使ったプロジェクトの例が多数紹介されている. ここにある例をテンプレートに自分のアプリケーションの開発を進めるとよい.

    Hands-on #1: 初めての EC2 インスタンスを起動する

    ハンズオンの第一回では, CDK を使って EC2 のインスタンス(仮想サーバー)を作成し,SSH でサーバーにログインする,という演習を行う. このハンズオンを終えれば,あなたは自分だけのサーバーを AWS 上に立ち上げ,自由に計算を走らせることができるようになるのである!

    準備

    ハンズオンのソースコードは GitHub の handson/ec2-get-started に置いてある.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行することができる.

    まずは,ハンズオンを実行するための環境を整える. これらの環境整備は,後のハンズオンでも前提となるものなので確実にミスなく行っていただきたい.

    • AWS Account: ハンズオンを実行するには個人の AWS アカウントが必要である. AWS アカウントの取得については AWS アカウントの取得 を参照のこと.
    • Python と Node.js: 本ハンズオンを実行するには,Python (3.6 以上),Node.js (12.0 以上) がインストールされていなければならない.
    • AWS CLI: AWS CLI のインストールについては, AWS CLI のインストール を参照. ここに記載されている認証鍵の設定も済ませておくこと.
    • AWS CDK: AWS CDK のインストールについては, AWS CDK のインストール を参照.
    • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    使用方法については ハンズオン実行用の Docker image の使い方 を参照のこと.

    SSH

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する (環境構築 を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    python
    class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    • まず最初に,VPC を定義する.

    • 次に, security group (SG) を定義している. ここでは,任意の IPv4 のアドレスからの,ポート 22 (SSH の接続に使用される)への接続を許可している. それ以外の接続は拒絶される.

    • 最後に,上記で作った VPC と SG が付与された EC2 インスタンスを作成している. インスタンスタイプは t2.micro を選択し, Amazon Linux を OS として設定している.

    それぞれについて,もう少し詳しく説明しよう.

    VPC (Virtual Private Cloud)

    VPC のアイコン.

    VPC

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    python
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

    • cidr="10.10.0.0/23" : このパラメータは,VPC 内の IPv4 のレンジを指定している. CIDR 記法については, Wikipediaなどを参照. 10.10.0.0/2310.10.0.0 から 10.10.1.255 までの 512 個の連続したアドレス範囲を指している. つまり,この VPC では最大で 512 個のユニークな IPv4 アドレスが使えることになる. 今回はサーバーは一つなので 512 個は明らかに多すぎるが,VPC はアドレスの数はどれだけ作成しても無料なので,多めに作成した.

    • subnet_configuration=... : このパラメータは,VPC にどのようなサブネットを作るか,を決めている. サブネットの種類には private subnetpublic subnet の二種類がある. private subnet は基本的にインターネットとは遮断されたサブネット環境である. インターネットと繋がっていないので,セキュリティは極めて高く, VPC 内のサーバーとのみ通信を行えばよい EC2 インスタンスはここに配置する. Public subnet とはインターネットに繋がったサブネットである. 本ハンズオンで作成するサーバーは,外から SSH でログインを行いたいので, Public subnet 内に配置する. より詳細な記述は 公式ドキュメンテーション を参照.

    • natgateways=0 : これは少し高度な内容なので省略する (興味のある読者は 公式ドキュメンテーションを参照). が,これを 0 にしておかないと,NAT Gateway の利用料金が発生してしまうので,注意!

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    python
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    EC2 (Elastic Compute Cloud)

    EC2 のアイコン.

    EC2

    EC2 は AWS 上に仮想サーバーを立ち上げるサービスである. 個々の起動状態にある仮想サーバーのことをインスタンス (instance) とよぶ (しかし,口語的なコミュニケーションにおいては,サーバーとインスタンスという言葉は相互互換的に用いられることが多い).

    EC2 では用途に応じて様々なインスタンスタイプが提供されている. table_title に,代表的なインスタンスタイプの例を挙げる (執筆時点での情報). EC2 のインスタンスタイプのすべてのリストは 公式ドキュメンテーション "Amazon EC2 Instance Types" で見ることができる.

    EC2 instance types
    InstancevCPUMemory (GiB)Network bandwidth (Gbps)Price per hour ($)

    t2.micro

    1

    1

    -

    0.0116

    t2.small

    1

    2

    -

    0.023

    t2.medium

    2

    4

    -

    0.0464

    c5.24xlarge

    96

    192

    25

    4.08

    c5n.18xlarge

    72

    192

    100

    3.888

    x1e.16xlarge

    64

    1952

    10

    13.344

    table_title からわかるように, CPU は 1 コアから 96 コアまで,メモリーは 1GB から 2TB 以上まで,ネットワーク帯域は最大で 100Gbps まで,幅広く選択することができる. また,時間あたりの料金は,CPU・メモリーの占有数にほぼ比例する形で増加する. EC2 はサーバーの起動時間を秒単位で記録しており,利用料金は使用時間に比例する形で決定される. 例えば, t2.medium のインスタンスを 10 時間起動した場合,0.0464 * 10 = 0.464 ドルの料金が発生する.

    AWS には 無料利用枠 というものがあり, t2.micro であれば月に 750 時間までは無料で利用することができる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    python
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, Hands-on #2: AWS でディープラーニングを実践 でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    さて,ハンズオンのコードの理解ができたところで,プログラムを実際に実行してみよう.繰り返しになるが, 準備 での準備ができていることが前提である.

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    sh
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は Python クイックガイド に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    AWS のシークレットキーをセットする

    AWS CLI および AWS CDK を使うには, AWS のシークレットキーが設定されている必要がある. シークレットキーの発行については AWS のシークレットキーの作成 を参照のこと. シークレットキーを発行したら, AWS CLI のインストール を参照し,コマンドラインの設定を行う.

    手順をここに短く要約すると,一つ目の方法は AWS_ACCESS_KEY_ID などの環境変数を設定するやり方である. もう一つの方法は, ~/.aws/credentials に認証情報を保存しておく方式である. シークレットキーの設定は AWS CLI/CDK を使用するうえで共通のステップになるので,しっかりと理解しておくように.

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    sh
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    sh
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    おめでとう!これで,めでたく AWS 上に EC2 仮想サーバーを起動し,リモートからアクセスできるようになった!

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    sh
    $ cat /proc/cpuinfo
    +
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB
    $ cat /proc/cpuinfo
    +
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    sh
    $  top -n 1
    +
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
    +
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    +
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
    +
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    sh
    $ sudo yum update -y
    +$ sudo yum install -y python36
    $ sudo yum update -y
    +$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    sh
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    EC2 コンソール画面

    コンソール右上で,正しいリージョン (今回の場合は ap-northeast-1, Tokyo) が選択されているか,注意する!

    前章で CloudFormation について触れたが,今回デプロイしたアプリケーションも,CloudFormation のスタックとして管理されている. スタック (stack) とは, AWS リソースの集合のことを指す. 今回の場合は, VPC/EC2/SG などがスタックの中に含まれている. コンソールで CloudFormation のページに行ってみよう (figure_title).

    CloudFormation コンソール画面

    "MyFirstEc2" という名前のスタックがあることが確認できる. クリックをして中身を見てみると,EC2, VPC などのリソースがこのスタックに紐付いていることがわかる.

    スタックを削除

    これにて,第一回のハンズオンで説明すべき事柄はすべて完了した. 最後に,使わなくなったスタックを削除しよう. スタックの削除には,二つの方法がある.

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    ここまでが,本書の第一部の内容である. 盛りだくさんの内容であったが,ついてこれたであろうか?

    クラウド概論 では,クラウドの定義と用語の説明を行ったあと,なぜクラウドを使うのか,という点を議論した. 続いて AWS 入門 では,クラウドを学ぶ具体的なプラットフォームとして AWS を取り上げ, AWS を使用するにあたり最低限必要な知識と用語の説明を行った. さらに, Hands-on #1: 初めての EC2 インスタンスを起動する のハンズオンでは AWS CLI と AWS CDK を使って,自身のプライベートなサーバーを AWS 上に立ち上げる演習を行った.

    これらを通じて,いかに簡単に (たった数行のコマンドで!) 仮想サーバーを立ち上げたり,削除したりすることができるか,体験できただろう. 筆者は,クラウド概論 でクラウドの最も重要な側面はダイナミックに計算リソースを拡大・縮小できることである,と述べた. この言葉の意味が,ハンズオンを通じてより明らかになっただろうか? ここで学んだ技術を少し応用するだけで,自分のウェブページをホストする仮想サーバーを作成したり,大量のコアを搭載した EC2 インスタンスを用意して科学計算を実行するなど,いろいろなアプリケーションが実現できる.

    次章からは,今回学んだクラウドの技術を基に,より現実に即した問題を解くことを体験してもらう. お楽しみに!

    クラウドで行う科学計算・機械学習

    計算機が発達した現代では,計算機によるシミュレーションやビッグデータの解析は,科学・エンジニアリングの研究の主要な柱である. これらの大規模な計算を実行するには,クラウドは最適である. 本章から始まる第二部では,どのようにしてクラウド上で科学計算を実行するのかを,ハンズオンとともに体験してもらう. 科学計算の具体的な題材として,今回は機械学習(深層学習)を取り上げる.

    なお,本書では PyTorch ライブラリを使って深層学習のアルゴリズムを実装するが,深層学習および PyTorch の知識は不要である. 講義ではなぜ・どうやって深層学習をクラウドで実行するかに主眼を置いているので,実行するプログラムの詳細には立ち入らない. 将来,自分で深層学習を使う機会が来たときに,詳しく学んでもらいたい.

    なぜ機械学習をクラウドで行うのか?

    2010 年頃に始まった第三次 AI ブームのおかげで,学術研究だけでなく社会・ビジネスの文脈でも機械学習に高い関心が寄せられている. とくに,深層学習 (ディープラーニング) とよばれる多層のレイヤーからなるニューラルネットワークを用いたアルゴリズムは,画像認識や自然言語処理などの分野で圧倒的に高い性能を実現し,革命をもたらしている.

    深層学習の特徴は,なんといってもそのパラメータの多さである. 層が深くなるほど,層間のニューロンを結ぶ重みパラメータの数が増大していく. たとえば,最新の言語モデルである GPT-3 には1750 億個ものパラメータが含まれている. このような膨大なパラメータを有することで,深層学習は高い表現力と汎化性能を実現しているのである.

    GPT-3 に限らず,最近の SOTA (State-of-the-art) の性能を達成するニューラルネットワークでは,百万から億のオーダーのパラメータを内包することは頻繁になってきている. そのような巨大なニューラルネットを訓練 (最適化) させるのは,当然のことながら膨大な計算コストがかかる. 結果として,ひとつの計算機では丸一日以上の時間がかかる場合も珍しくない. 深層学習の発展の速度は目覚ましく,研究・ビジネス両方の観点からも,いかにスループットよくニューラルネットワークの最適化を行えるかが鍵となってくる. そのような問題を解決するのにとても有効な手段が,クラウドである! Hands-on #1: 初めての EC2 インスタンスを起動する でその片鱗を見たように,クラウドを使用することでゼロから数千に至るまでの数のインスタンスを動的に起動し,並列に計算を実行することができる. さらに,深層学習を加速させる目的で,深層学習の演算に専用設計された計算チップ (GPU など) がある. クラウドを利用すると,そのような専用計算チップも無尽蔵に利用することができる. 事実,先述した GPT-3 の学習も,詳細は明かされていないが,Microsoft 社のクラウドを使って行われたと報告されている.

    GPU による深層学習の高速化

    深層学習の計算で欠かすことのできない技術として, GPU (Graphics Processing Unit) について少し説明する.

    GPU は,その名のとおり,元々はコンピュータグラフィックスを出力するための専用計算チップである. CPU (Central Processing Unit) に対し,グラフィックスの演算に特化した設計がなされている. 身近なところでは, XBox や PS5 などのゲームコンソールなどに搭載されているし,ハイエンドなノート型・デスクトップ型計算機にも搭載されていることがある. コンピュータグラフィックスでは,スクリーンにアレイ状に並んだ数百万個の画素をビデオレート (30 fps) 以上で処理する必要がある. そのため,GPU はコアあたりの演算能力は比較的小さいかわりに,チップあたり数百から数千のコアを搭載しており (figure_title),スクリーンの画素を並列的に処理することで,リアルタイムでの描画を実現している.

    GPUのアーキテクチャ.GPUには数百から数千の独立した計算コアが搭載されている. (画像出典: https://devblogs.nvidia.com/nvidia-turing-architecture-in-depth/)

    このように,コンピュータグラフィクスの目的で生まれた GPU だが,2010 年前後から,その高い並列計算能力をグラフィックス以外の計算 (科学計算など) に用いるという流れ (General-purpose computing on GPU; GPGPU) が生まれた. GPU のコアは,その設計から,行列の計算など,単純かつ規則的な演算が得意であり,そのような演算に対しては数個程度のコアしかもたない CPU に比べて圧倒的に高い計算速度を実現することができる. 現在では GPGPU は分子動力学や気象シミュレーション,そして機械学習など多くの分野で使われている.

    ディープラーニングで最も頻繁に起こる演算が,ニューロンの出力を次の層のニューロンに伝える畳み込み (Convolution) 演算である (figure_title). 畳み込み演算は,まさに GPU が得意とする演算であり, CPU ではなく GPU を用いることで学習を飛躍的に (最大で数百倍程度) 加速させることができる.

    ニューラルネットワークにおける畳み込み演算.

    このように GPU は機械学習の計算で欠かせないものであるが,なかなか高価である. たとえば,科学計算・機械学習に専用設計された NVIDIA 社の Tesla V100 というチップは,一台で約百万円の価格が設定されている. 機械学習を始めるのに,いきなり百万円の投資はなかなか大きい. だが,クラウドを使えば,初期コスト0で GPU を使用することができる.

    機械学習を行うのに, V100 が必ずしも必要というわけではない. むしろ,研究者などでしばしば行われるのは,コンピュータゲームに使われるグラフィックス用の GPU を買ってきて (NVIDIA GeForce シリーズなど),開発のときはをそれを用いる,というアプローチである. グラフィックス用のいわゆる"コンシューマ GPU"は,市場の需要が大きいおかげで,10 万円前後の価格で購入することができる. V100 と比べると,コンシューマ GPU はコアの数が少なかったり,メモリーが小さかったりなどで劣る点があるが, それらを除いては計算能力にとくに制限があるわけではなく,開発の段階では十分な性能である場合がほとんどである. プログラムができあがって,ビッグデータの解析や,モデルをさらに大きくしたいときなどに,クラウドは有効だろう.

    クラウドで GPU を使うには, GPU が搭載された EC2 インスタンスタイプ (P3, P2, G3, G4 など) を選択しなければならない. table_title に,代表的な GPU 搭載のインスタンスタイプを挙げる (執筆時点での情報).

    GPUを搭載したEC2インスタンスタイプ
    InstanceGPUsGPU modelGPU Mem (GiB)vCPUMem (GiB)Price per hour ($)

    p3.2xlarge

    1

    NVIDIA V100

    16

    8

    61

    3.06

    p3n.16xlarge

    8

    NVIDIA V100

    128

    64

    488

    24.48

    p2.xlarge

    1

    NVIDIA K80

    12

    4

    61

    0.9

    g4dn.xlarge

    1

    NVIDIA T4

    16

    4

    16

    0.526

    table_title からわかるとおり, CPU のみのインスタンスと比べると少し高い価格設定になっている. また,古い世代の GPU (V100 に対しての K80) はより安価な価格で提供されている. 1 インスタンスあたりの GPU の搭載数は 1 台から最大で 8 台まで選択することが可能である.

    GPU を搭載した一番安いインスタンスタイプは, g4dn.xlarge であり,これには廉価かつ省エネルギー設計の NVIDIA T4 が搭載されている. 後のハンズオンでは,このインスタンスを使用して,ディープラーニングの計算を行ってみる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    V100 を一台搭載した p3.2xlarge の利用料金は一時間あたり $3.06 である. V100 が約百万円で売られていることを考えると,約 3000 時間 (= 124 日間),通算で計算を行った場合に,クラウドを使うよりも V100 を自分で買ったほうがお得になる,という計算になる (実際には,自前で V100 を用意する場合は, V100 だけでなく, CPU やネットワーク機器,電気使用料も必要なので,百万円よりもさらにコストがかかる).

    GPT-3 で使われた計算リソースの詳細は論文でも明かされていないのだが, Lambda 社のブログで興味深い考察が行われている (Lambda 社は機械学習に特化したクラウドサービスを提供している).

    記事によると,1750 億のパラメータを訓練するには,一台の GPU (NVIDIA V100) を用いた場合,342 年の月日と 460 万ドルのクラウド利用料が必要となる,とのことである. GPT-3 のチームは,複数の GPU に処理を分散することで現実的な時間のうちに訓練を完了させたのであろうが,このレベルのモデルになってくるとクラウド技術の限界を攻めないと達成できないことは確かである.

    深層学習を詳しく勉強したい人には以下の参考書を推薦したい. 深層学習の基礎的な概念や理論は普遍的であるが,この分野は日進月歩なので,常に最新の情報を取り入れることを忘れずに.

    Hands-on #2: AWS でディープラーニングを実践

    準備

    ハンズオン第二回では, GPU を搭載した EC2 インスタンスを起動し,深層学習モデルの学習と推論を実行する演習を行う.

    ハンズオンのソースコードは GitHub の handson/mnist に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. それ以外に必要な準備はない.

    初期状態の AWS アカウントでは, GPU 搭載の G タイプのインスタンスの起動上限が 0 になっていることがある. これを確認するには, AWS コンソールから EC2 の画面を開き,左のメニューから Limits を選択する. その中の Running On-Demand All G instances という数字が G インスタンスの起動上限を表している.

    もし,これが 0 になっていた場合は, AWS の自動申請フォームから上限緩和のリクエストを送る必要がある. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,東京 (ap-northeast-1) リージョンでは 0.71 $/hour のコストが発生する.

    AWS Educate Starter Account を使用している読者へ: 執筆時点においては, Starter Account には GPU 搭載型インスタンスを起動できないという制限が設けられている. したがって, Starter Account のユーザーはこのハンズオンを実行することはできない. 興味のある読者は,制限のない一般アカウントを自分自身で取得する必要があることに注意.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#2で作製するアプリケーションのアーキテクチャ

    図の多くの部分が,第一回ハンズオンで作成したアプリケーションと共通していることに気がつくだろう. 少しの変更で,簡単にディープラーニングを走らせる環境を構築することができるのである!主な変更点は次の3点である.

    • GPU を搭載した g4dn.xlarge インスタンスタイプを使用

    • ディープラーニングに使うプログラムがあらかじめインストールされた DLAMI (後述) を使用

    • SSH にポートフォワーディングのオプションつけてサーバーに接続し,サーバーで起動している Jupyter Notebook (後述) を使ってプログラムを書いたり実行したりする

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    python
    class Ec2ForDl(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class Ec2ForDl(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, クラウドで行う科学計算・機械学習 ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

    • ここでは,Deep Learning 用の諸々のソフトウェアがプリンストールされた AMI (Deep Learning Amazon Machine Image; DLAMI) を選択している (第一回では,Amazon Linux という AMI を使用していた). 使用する AMI の ID は リージョンごとに指定する必要があり,ここでは us-east-1ap-northeast-1 でそれぞれ定義している.

    DLAMI という新しい概念が出てきたので,説明しよう.

    AMI が us-east-1ap-northeast-1 でしか定義されていないので,提供されているコードはこの二つのリージョンのみでデプロイ可能である. もしほかのリージョンを利用したい場合は, AMI の ID を自身で検索し,コードに書き込む必要がある.

    DLAMI (Deep Learning Amazon Machine Image)

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    最も low-level なレイヤーとしては, GPU ドライバー がインストールされている. GPU ドライバーなしには OS は GPU とコマンドのやり取りをすることができない. 次のレイヤーが CUDAcuDNN である. CUDA は, NVIDIA 社が開発した, GPU 上で汎用コンピューティングを行うための言語であり, C++ 言語を拡張したシンタックスを備える. cuDNN は CUDA で書かれたディープラーニングのライブラリであり,n 次元の畳み込みなどの演算が実装されている. ここまでが, "Base" とよばれるタイプの DLAMI の中身である.

    これに加えて, "Conda" とよばれるタイプには, "Base" のプログラム基盤の上に, TensorFlowPyTorch などのライブラリがインストールされている. さらに, Anaconda による仮想環境を使うことによって, TensorFlow の環境・ PyTorch の環境・ MxNet の環境など,フレームワークを簡単に切り替えることができる (これについては,後のハンズオンで触れる). また, Jupyter Notebook もインストール済みである.

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    +
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    +
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    SSH ログインコマンドの <IP address> 部分は自身のインスタンスの IP アドレスを代入することを忘れずに.

    本書の提供している Docker を使ってデプロイを実行した人へ

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    Jupyter Notebook とは,インタラクティブに Python のプログラムを書いたり実行したりするためのツールである. Jupyter は GUI としてウェブブラウザを介してアクセスする形式をとっており,まるでノートを書くように,プロットやテーブルのデータも美しく表示することができる (figure_title). Python に慣れている読者は,きっと一度は使ったことがあるだろう.

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    sh
    $ cd ~ # go to home directory
    +$ jupyter notebook
    $ cd ~ # go to home directory
    +$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    Jupyter Notebook の使い方 (超簡易版)

    • Shift + Enter: セルを実行

    • Esc: Command mode に遷移

    • メニューバーの "+" ボタン または Command mode で A ⇒ セルを追加

    • メニューバーの "ハサミ" ボタン または Command mode で X ⇒ セルを削除

    ショートカットの一覧などは Ventsislav Yordanov 氏によるブログ が参考になる.

    PyTorch はじめの一歩

    PyTorch は Facebook AI Research LAB (FAIR) が中心となって開発を進めている,オープンソースのディープラーニングのライブラリである. PyTorch は 有名な例で言えば Tesla 社の自動運転プロジェクトなどで使用されており,執筆時点において最も人気の高いディープラーニングライブラリの一つである. 本ハンズオンでは, PyTorch を使ってディープラーニングの実践を行う.

    PyTorch の歴史のお話

    Facebook は PyTorch のほかに Caffe2 とよばれるディープラーニングのフレームワークを開発していた (初代 Caffe は UC Berkley の博士課程学生だった Yangqing Jia によって創られた). Caffe2 は 2018 年に PyTorch プロジェクトに合併された.

    また,2019 年 12 月,日本の Preferred Networks 社が開発していた Chainer も開発を終了し,PyTorch の開発チームと協業していくことが発表された (詳しくは プレスリリース を参照). PyTorch には,開発統合前から Chainer からインスパイアされた API がいくつもあり, Chainer の DNA は今も PyTorch に引き継がれているのである…!

    本格的なディープラーニングの計算に移る前に, PyTorch ライブラリを使って, GPU で計算を行うとはどういうものか,その入り口に触れてみよう.

    まずは,新しいノートブックを作成する. Jupyter のホーム画面の右上の "New" を押し,"conda_pytorch_p36" という環境を選択したうえで,新規ノートブックを作成する (figure_title). "conda_pytorch_p36" の仮想環境には, PyTorch がインストール済みである.

    新規ノートブックの作成. "conda_pytorch_p36" の環境を選択する.

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    python
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    python
    x = torch.rand(3,3)
    +print(x)
    x = torch.rand(3,3)
    +print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    python
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    python
    z = x + y
    +print(z)
    z = x + y
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    python
    z = z.to("cpu")
    +print(z)
    z = z.to("cpu")
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    完成した Jupyter Notebook は /handson/mnist/pytorch/pytorch_get_started.ipynb にある. Jupyter の画面右上の "Upload" からこのファイルをアップロードして,コードを走らせることが可能である.

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    python
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +
    +%time z = torch.matmul(x,y)
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +
    +%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    python
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
    +
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
    +
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    このベンチマークでは, dtype=torch.float32 と指定することで,32bit の浮動小数点型を用いている. ディープラーニングの学習および推論の計算には,32bit 型,場合によっては 16bit 型が使われるのが一般的である. これの主な理由として,教師データやミニバッチに起因するノイズが,浮動小数点の精度よりも大きいことがあげられる. 32bit/16bit を採用することで,メモリー消費を抑えたり,計算速度の向上が達成できる.

    上記のベンチマークから,GPU を用いることで,約 10 倍のスピードアップを実現することができた. スピードアップの性能は,演算の種類や行列のサイズに依存する. 行列積は,そのなかでも最も速度向上が見込まれる演算の一つである.

    実践ディープラーニング! MNIST 手書き数字認識タスク

    ここまで,AWS 上でディープラーニングの計算をするための概念や前提知識をながながと説明してきたが,ついにここからディープラーニングの計算を実際に走らせてみる.

    ここでは,機械学習のタスクで最も初歩的かつ有名な MNIST データセットを使った数字認識を扱う (figure_title). これは,0 から 9 までの手書きの数字の画像が与えられ,その数字が何の数字なのかを当てる,というシンプルなタスクである.

    MNIST 手書き数字データセット

    今回は, MNIST 文字認識タスクを,畳み込みニューラルネットワーク (Convolutional Neural Network; CNN) を使って解く. ソースコードは /handson/minist/pytorch/ にある mnist.ipynbsimple_mnist.py である. なお,このプログラムは, PyTorch の公式 Example Project 集 を参考に,多少の改変を行ったものである.

    まずは,カスタムのクラスや関数が定義された simple_mnist.py をアップロードしよう (figure_title). 画面右上の "Upload" ボタンをクリックし,ファイルを選択することでアップロードができる. この Python プログラムの中に,CNN のモデルや,学習の各イテレーションにおけるパラメータの更新などが記述されている. 今回はこの中身を説明することはしないが,興味のある読者は自身でソースコードを読んでみるとよい.

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    python
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
    +
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
    +
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    python
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
    +
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
    +
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    python
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
    +
    +print("Example data size:", example_data.shape)
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
    +
    +print("Example data size:", example_data.shape)
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    python
    model = Model()
    +model.to("cuda") # load to GPU
    model = Model()
    +model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    python
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\\n")
    +
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\\n")
    +
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    python
    model.eval()
    +
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    model.eval()
    +
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は スタックを削除 参照).

    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    Docker 入門

    ここまでの章で扱ってきたハンズオンでは,単一のサーバーを立ち上げ,それに SSH でログインをして,コマンドを叩くことで計算を行ってきた. いわば,パーソナルコンピュータの延長のような形でクラウドを使ってきたわけである. このような,インターネットのどこからでもアクセスできるパーソナルコンピュータとしてのクラウドという使い方も,もちろん便利であるし,いろいろな応用の可能性がある. しかし,これだけではクラウドの本当の価値は十分に発揮されていないと言うべきだろう. クラウド概論 で述べたように,現代的なクラウドの一番の強みは自由に計算機の規模を拡大できることにある. すなわち,多数のサーバーを同時に起動し,複数のジョブを分散並列的に実行させることで大量のデータを処理してこそ,クラウドの本領が発揮されるのである.

    本章からはじまる 3 章分 (Docker 入門, Hands-on #3: AWS で自動質問回答ボットを走らせる, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) を使って,クラウドを利用することでどのように大規模な計算システムを構築しビッグデータの解析に立ち向かうのか,その片鱗をお見せしたい. とくに,前章で扱った深層学習をどのようにビッグデータに適用していくかという点に焦点を絞って議論していきたい. そのための前準備として,本章では Docker とよばれる計算機環境の仮想化ソフトウェアを紹介する (figure_title). 現代のクラウドは Docker なしには成り立たないといっても過言ではないだろう. クラウドに限らず,ローカルで行う計算処理にも Docker は大変便利である. AWS からは少し話が離れるが,しっかりと理解して前に進んでもらいたい.

    機械学習の大規模化

    先ほどから"計算システムの大規模化"と繰り返し唱えているが,それは具体的にはどのようなものを指しているのか? ここでは大規模データを処理するための計算機システムを,機械学習を例にとって見てみよう.

    クラウドで行う科学計算・機械学習 で紹介した GPT-3 のような,超巨大な数のパラメータを有する深層学習モデルを学習させたいとしよう. そのような計算を行いたい場合,一つのサーバーでは計算力が到底足りない. したがって,典型的には figure_title に示すような計算システムの設計がなされる. すなわち,大量の教師データを小さなチャンクとして複数のマシンに分散し,並列的にニューラルネットのパラメータを最適化していくという構造である.

    複数の計算機を使った大規模な深層学習モデルの訓練

    あるいは,学習済みのモデルを大量のデータに適用し,解析を行いたいとしよう. たとえば, SNS のプラットフォームで大量の画像が与えられて,それぞれの写真に何が写っているのかをラベルづけする,などのアプリケーションを想定できる. そのような場合は, figure_title のようなアーキテクチャが考えられるだろう. すなわち,大量のデータを複数のマシンで分割し,それぞれのマシンで推論の計算を行うというような構造である.

    複数の計算機による深層学習モデルを使った推論計算

    このような複数の計算機を同時に走らせるようなアプリケーションをクラウド上で実現するには,どのようにすればよいのだろうか?

    重要なポイントとして, figure_titlefigure_title で起動している複数のマシンは,基本的に全く同一の OS・計算環境を有している点である. ここで,個人のコンピュータで行うようなインストールの操作を,各マシンで行うこともできるが,それは大変な手間であるし,メンテナンスも面倒だろう. すなわち,大規模な計算システムを構築するには,簡単に計算環境を複製できるような仕組みが必要であるということがわかる.

    そのような目的を実現するために使われるのが, Docker とよばれるソフトウェアである.

    Docker とは

    Docker のアイコン

    Docker とは, コンテナ (Container) とよばれる仮想環境下で,ホスト OS とは独立した別の計算環境を走らせるためのソフトウェアである. Docker を使うことで, OS を含めたすべてのプログラムをコンパクトにパッケージングすることが可能になる (パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ). Docker を使うことで,クラウドのサーバー上に瞬時に計算環境を複製することが可能になり, figure_title で見たような複数の計算機を同時に走らせるためのシステムが実現できる.

    Docker は 2013 年に Solomon Hykes らを中心に開発され,それ以降爆発的に普及し,クラウドコンピューティングだけでなく,機械学習・科学計算の文脈などでも欠かすことのできないソフトウェアとなった. Docker はエンタープライズ向けの製品を除き無料で使用することができ,コアの部分は オープンソースプロジェクト として公開されている. Docker は Linux, Windows, Mac いずれの OS でも提供されている. 概念としては, Docker は仮想マシン (Virtual machine; VM) にとても近い. ここでは, VM との対比をしながら,Docker とはなにかを簡単に説明しよう.

    仮想マシン (VM) とは,ホストとなるマシンの上に,仮想化された OS を走らせる技術である (figure_title). VM には ハイパーバイザー (Hypervisor) とよばれるレイヤーが存在する. Hypervisor はまず,物理的な計算機リソース (CPU, RAM, network など) を分割し,仮想化する. たとえば, ホストマシンに物理的な CPU が 4 コアあるとして,ハイパーバイザーはそれを (2,2) 個の組に仮想的に分割することができる. VM 上で起動する OS には,ハイパーバイザーによって仮想化されたハードウェアが割り当てられる. VM 上で起動する OS は基本的に完全に独立であり,たとえば OS-A は OS-B に割り当てられた CPU やメモリー領域にアクセスすることはできない (これを isolation とよぶ). VM を作成するための有名なソフトウェアとしては, VMwareVirtualBoxXen などがある. また,これまで触ってきた EC2 も,基本的に VM 技術を使うことで所望のスペックをもった仮想マシンがユーザーに提示される.

    Docker も, VM と同様に,仮想化された OS をホストの OS 上に走らせるための技術である. VM に対し, Docker ではハードウェアレベルの仮想化は行われておらず,すべての仮想化はソフトウェアレベルで実現されている (figure_title). Docker で走る仮想 OS は,多くの部分をホストの OS に依存しており,結果として非常にコンパクトである. その結果, Docker で仮想 OS を起動するために要する時間は, VM に比べて圧倒的に早い. また, パッケージ化された環境 (=イメージ) のサイズも完全な OS に比べ圧倒的に小さくなるので,ネットワークを通じたやり取りが非常に高速化される点も重要である 加えて, VM のいくつかの実装では,メタル (仮想化マシンに対して,物理的なハードウェア上で直接起動する場合のこと) と比べ,ハイパーバイザーレイヤーでのオーバーヘッドなどにより性能が低下することが知られているが, Docker ではメタルとほぼ同様の性能を引き出すことができるとされている.

    その他, VM との相違点などはたくさんあるのだが,ここではこれ以上詳細には立ち入らない. 大事なのは, Docker とはとてもコンパクトかつハイパフォーマンスな仮想計算環境を作るツールである,という点である. その手軽さゆえに,2013 年の登場以降,クラウドシステムでの利用が急速に増加し,現代のクラウドでは欠くことのできない中心的な技術になっている.

    Docker (左) と VM (右) の比較 (画像出典: https://www.docker.com/blog/containers-replacing-virtual-machines/)

    職業的プログラマーにとっての"三種の神器"とはなんだろうか? 多様な意見があると思うが,筆者は Git, Vim そして Docker を挙げたい.

    Git は多くの読者がご存じの通り,コードの変更を追跡するためのシステムである. Linux の作成者である Linus Torvalds によって 2005 年に誕生した. チームでの開発を進める際には欠かせないツールだ.

    Vim は 1991 年から 30 年以上の間プログラマーたちに愛されてきたテキストエディターである. Stackoverflow が行った 2019 年のアンケート によると,開発環境の部門で 5 位の人気を獲得している. たくさんのショートカットと様々なカスタム設定が提供されているので,初見の人にはなかなかハードルが高いが,一度マスターすれば他のモダンなエディターや統合開発環境に負けない,あるいはそれ以上の開発体験を実現することができる.

    これらの十年以上の歴史あるツールに並んで,第三番目の三種の神器として挙げたいのが Docker だ. Docker はプログラマーの開発のワークフローを一変させた. たとえば,プロジェクトごとに Docker イメージを作成することで,どの OS・コンピュータ でも全く同じ計算環境で開発・テストを実行することができるようになった. また, DevOpsCI / CD (Continuous Integration / Continuous Deployment) といった最近の開発ワークフローも Docker のようなコンテナ技術の存在に立脚している. さらにはサーバーレスコンピューティング (Serverless architecture) といった概念も,コンテナ技術の生んだ大きな技術革新といえる.

    あなたにとっての三種の神器はなんだろうか? また,これからの未来ではどんな新しいツールが三種の神器としてプログラマーのワークフローを革新していくだろうか?

    Docker チュートリアル

    Docker とはなにかを理解するためには,実際に触って動かしてみるのが一番有効な手立てである. ここでは, Docker の簡単なチュートリアルを行っていく.

    Docker のインストールについては, Docker のインストール および 公式のドキュメンテーション を参照してもらいたい. Docker のインストールが完了している前提で,以下は話を進めるものとする.

    Docker 用語集

    Docker を使い始めるに当たり,最初に主要な用語を解説しよう. 次のパラグラフで太字で強調された用語を頭に入れた上で,続くチュートリアルに取り組んでいただきたい.

    Docker を起動する際の大まかなステップを示したのが figure_title である. パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ. イメージは, Docker Hub などのリポジトリで配布されているものをダウンロードするか,自分でカスタムのイメージを作成することも可能である. イメージを作成するための”レシピ”を記述したファイルが Dockerfile である. Dockerfile からイメージを作成する操作を build とよぶ. イメージがホストマシンのメモリにロードされ,起動状態にある計算環境のことを コンテナ (Container) とよぶ. Container を起動するために使用されるコマンドが run である.

    Image と Container

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, Hands-on #2: AWS でディープラーニングを実践 でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    sh
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    python
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
    +
    +RUN apt-get update \\
    +    && apt-get install nano
    +
    +#
    +RUN cd /opt \\
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \\
    +    && tar -xzf Python-3.7.6.tgz \\
    +    && cd Python-3.7.6 \\
    +    && ./configure --enable-optimizations \\
    +    && make install
    +
    +RUN cd /opt \\
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \\
    +    && unzip awscliv2.zip \\
    +    && ./aws/install
    +
    +#
    +RUN npm install -g aws-cdk@1.100
    +
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
    +
    +# copy hands-on source code in /root/
    +COPY handson/ /root/handson
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
    +
    +RUN apt-get update \\
    +    && apt-get install nano
    +
    +#
    +RUN cd /opt \\
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \\
    +    && tar -xzf Python-3.7.6.tgz \\
    +    && cd Python-3.7.6 \\
    +    && ./configure --enable-optimizations \\
    +    && make install
    +
    +RUN cd /opt \\
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \\
    +    && unzip awscliv2.zip \\
    +    && ./aws/install
    +
    +#
    +RUN npm install -g aws-cdk@1.100
    +
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
    +
    +# copy hands-on source code in /root/
    +COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    Singularity は科学計算や HPC (High Performance Computing) の分野で人気の高いコンテナプラットフォームである. Singularity では大学・研究機関の HPC クラスターでの運用に適したような設計が施されている. たとえば, Docker は基本的には root 権限で実行されるのに対し, Singularity はユーザー権限 (コマンドを実行したユーザー自身) でプログラムが実行される. root 権限での実行は Web サーバーのように個人・企業がある特定のサービスのために運用するサーバーでは問題ないが,多数のユーザーが多様な目的で計算を実行する HPC クラスターでは問題となる. また,Singularity は独自のイメージの作成方法・エコシステムをもっているが, Docker イメージを Singularity のイメージに変換し実行する機能も有している.

    podman は Red Hat 社によって開発されたもう一つのコンテナプラットフォームである. podman は基本的に Docker と同一のコマンドを採用しているが,実装は Red Hat によってスクラッチから行われた. podman では, Singularity と同様にユーザー権限でのプログラムの実行を可能であり,クラウドおよび HPC の両方の環境に対応するコンテナプラットフォームを目指して作られた. また,その名前にあるとおり pod とよばれる独自の概念が導入されている.

    著者の個人的な意見としては,現時点では Docker をマスターしておけば当面は困ることはないと考えるが,興味のある読者はぜひこれらのツールも試してみてはいかがだろうか?

    Elastic Container Service (ECS)

    ECS のアイコン

    ここまでに説明してきたように, Docker を使うことで仮想計算環境を簡単に複製・起動することが可能になる. 本章の最後の話題として, AWS 上で Docker を使った計算システムを構築する方法を解説しよう.

    Elastic Container Service (ECS) とは, Docker を使った計算機クラスターを AWS 上に作成するためのツールである (figure_title). ECS を使用することで, Docker にパッケージされたアプリケーションを計算機クラスターに投入したり,計算機クラスターのインスタンスを追加・削除する操作 (=スケーリング) を行うことができる.

    ECS の概要を示したのが figure_title である. ECS は,タスク (Task) と呼ばれる単位で管理された計算ジョブを受け付ける. システムにタスクが投入されると,ECS は最初にタスクで指定された Docker イメージを外部レジストリからダウンロードしてくる. 外部レジストリとしては, Docker Hub や AWS 独自の Docker レジストリである ECR (Elastic Container Registry) を指定することができる.

    ECS の次の重要な役割はタスクの配置である. あらかじめ定義されたクラスター内で,計算負荷が小さい仮想インスタンスを選び出し,そこに Docker イメージを配置することで指定された計算タスクが開始される. "計算負荷が小さい仮想インスタンスを選び出す" と言ったが,具体的にどのような戦略・ポリシーでこの選択を行うかは,ユーザーの指定したパラメータに従う.

    また,クラスターのスケーリングも ECS における重要な概念である. スケーリングとは,クラスター内のインスタンスの計算負荷をモニタリングし,計算負荷に応じてインスタンスの起動・停止を行う操作を指す. クラスター全体の計算負荷が指定された閾値 (たとえば 80%の稼働率) を超えていた場合,新たな仮想インスタンスをクラスター内に立ち上げる操作を scale-out (スケールアウト) とよび, 負荷が減った場合に不要なインスタンスを停止する操作を scale-in (スケールイン) とよぶ. クラスターのスケーリングは, ECS がほかの AWS のサービスと連携することで実現される. 具体的には, EC2 の Auto scaling group (ASG)Fargate の2つの選択肢が多くの場合選択される. ASG については Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する, Fargate については Hands-on #3: AWS で自動質問回答ボットを走らせる でより詳細に解説する.

    これら一連のタスクの管理を, ECS は自動でやってくれる. クラスターのスケーリングやタスクの配置に関してのパラメータを一度指定してしまえば,ユーザーは (ほとんどなにも考えずに) 大量のタスクを投入することができる. クラスターのスケーリングによってタスクの量にちょうど十分なだけのインスタンスが起動し,タスクが完了した後は不要なインスタンスはすべて停止される.

    さて,ここまで説明的な話が続いてしまったが,次章からは早速 Docker と AWS を使って大規模な並列計算システムを構築していこう!

    ECS の概要

    Hands-on #3: AWS で自動質問回答ボットを走らせる

    ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.

    通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 (Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.

    Fargate

    ハンズオンに入っていく前に, Fargate という AWS の機能を知っておく必要がある (figure_title).

    Fargate のアイコン

    ECS の概要を示した figure_title をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. EC2 あるいは Fargate のいずれかである. EC2 を用いた場合は,先の章 (Hands-on #1: 初めての EC2 インスタンスを起動する, Hands-on #2: AWS でディープラーニングを実践) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 (Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) で説明することにする.

    Fargate とは, ECS での利用に特化して設計された,コンテナを使用した計算タスクを走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は docker run のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.

    Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは 公式ドキュメンテーション "Amazon ECS on AWS Fargate" 参照). クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.

    以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.

    厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.

    準備

    ハンズオンのソースコードは GitHub の handson/qa-bot にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \\"the world's most famous equation\\". He received the 1921 Nobel Prize in Physics \\"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \\"the world's most famous equation\\". He received the 1921 Nobel Prize in Physics \\"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    sh
    answer: 1921
    answer: 1921

    人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

    今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."\n$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."\n$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    sh
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    sh
    $ question="Why did Einstein win the Nobel prize ?"\n$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"\n$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    出力:

    sh
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    今回提供する Q-A ボットの Docker のソースコードは https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile にある.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,以下のような設計である.

    • クライアントは,質問を AWS 上のアプリケーションに送信する.

    • 質問のタスクは ECS によって処理される.

    • ECS は, Docker Hub から,イメージをダウンロードする.

    • 次に,ECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.

      • このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.
    • ジョブが実行される.

    • ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.

    • 最後に,クライアントは DynamoDB から質問への回答を読み取る.

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    sh
    class EcsClusterQaBot(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
    +
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
    +
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
    +
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
    +
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    class EcsClusterQaBot(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
    +
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
    +
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
    +
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
    +
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

    • ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.

    • ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.

    • ここで,実行するタスクを定義している (task definition).

    • ここで, タスクの実行で使用する Docker イメージを定義している.

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    sh
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
    +
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
    +
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
    +
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
    +
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.

    このコードで cpu=1024 と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は 公式ドキュメンテーション "Amazon ECS on AWS Fargate" を参照のこと.

    CPU ユニットと 指定可能なメモリー量の換算表

    CPU ユニット

    メモリーの値

    256 (.25 vCPU)

    0.5 GB, 1 GB, 2 GB

    512 (.5 vCPU)

    1 GB, 2 GB, 3 GB, 4 GB

    1024 (1 vCPU)

    2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB

    2048 (2 vCPU)

    Between 4 GB and 16 GB in 1-GB increments

    4096 (4 vCPU)

    Between 8 GB and 30 GB in 1-GB increments

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. figure_title で, FARGATE という文字の下に 0 Running tasks, 0 Pending tasks と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.

    ECS コンソール画面

    続いて,この画面の左のメニューバーから Task Definitions という項目を見つけ,クリックしよう. 移動した先のページで EcsClusterQaBotEcsClusterQaBotTaskDefXXXX という項目が見つかるので,開く. 開いた先のページをスクロールすると figure_title に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.

    Task definition の確認

    タスクの実行

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, "Tasks" という名前のタブがあるので,それを開く (figure_title). すると,実行中のタスクの一覧が表示されるだろう.

    ECS のタスクの実行状況をモニタリング

    figure_title で見て取れるように, "Last status = Pending" となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.

    しばらく待つうちに, Status が "RUNNING" に遷移し,計算が始まる. 計算が終わると, Status は "STOPPED" に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.

    figure_title の画面から, "Task" の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (figure_title). "Last status", "Platform version" など,タスクの情報が表示されている. また, "Logs" のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.

    質問タスクの実行結果

    さて, run_task.py を実行したコマンドラインに戻ってきてみると, figure_title のような出力が得られているはずである. "Momotaro" という正しい回答が返ってきている!

    質問タスクの実行結果

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する

    ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

    本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

    Auto scaling groups (ASG)

    ハンズオンに入っていく前に, Auto scaling groups (ASG) とよばれる EC2 の概念を知っておく必要がある.

    ECS の概要を示した figure_title を振り返って見てほしい. 前章 (Hands-on #3: AWS で自動質問回答ボットを走らせる) でも説明したが, ECS のクラスターで計算を担う実体としては EC2 と Fargate を指定することができる. Fargate については前章で記述した. Fargate を用いると,自在にスケールする計算環境をとても簡単な設定で構築することができた. しかし, GPU を利用することができないなど,いくつかの制約があった. EC2 を使用した計算環境を指定することで,プログラミングの複雑度は増すが, GPU やその他のより高度かつ複雑な設定を伴ったクラスターを構築することができる.

    EC2 クラスターには ASG と呼ばれるサービスが配置される. ASG は複数の EC2 インスタンスをロジカルな単位でグループ化することでクラスターを構成する. ASG はクラスター内に新しいインスタンスを起動する,あるいは不要になったインスタンスを停止するなどのスケーリングを担う. ASG で重要な概念として, desired capacity, minimum capacity, maximum capacity というパラメータがある. minimum capacity, maximum capacity は,それぞれクラスター内に配置できるインスタンスの数の最小値・最大値を指定するパラメータである. 前者は,クラスターに負荷がかかっていない場合でもアイドリング状態にあるインスタンスを維持することで,急に負荷が増大した時などのバッファーとして作用することができる. 後者は,負荷が急に増えたときに,過剰な数のインスタンスが起動する事態を防ぎ,経済的なコストの上限を定める役割を果たす.

    desired capacity が,その時々でシステムが要求するインスタンスの数を指定する. desired capacity は,例えば 24 時間のリズムに合わせてインスタンスの数を増減させる (昼は多く夜は少なくなど) などの決まったスケジュールに基づいた設定を適用することができる. あるいはクラスター全体にかかっている負荷に応じて, desired capacity を動的に制御することも可能である. どのような基準でクラスターのスケーリングを行うかを定めるルールのことを,スケーリングポリシーとよぶ. たとえば,クラスター全体の稼働率 (負荷) を常に 80% に維持する,などのスケーリングポリシーが想定できる. この場合,クラスター全体の負荷が 80%を下回ったときにはクラスターからインスタンスが削除され,80%を超える (あるいは超えると予測される) 場合はインスタンスを追加する,という操作が ASG によって自動的に行われる.

    上記のようなパラメータを検討し,ユーザーは ASG を作成する. ASG を作成したのち, ECS との連携をプログラムしてあげることで, ECS を介して ASG による EC2 クラスターにタスクを投入することが可能になる.

    AWS Batch

    AWS Batch のアイコン

    先に説明したように, ECS と ASG を組み合わせることで,所望の計算クラスターを構築することが可能である. しかしながら, ECS と ASG にはかなり込み入った設定が必要であり,初心者にとっても経験者にとってもなかなか面倒なプログラミングが要求される. そこで, ECS と ASG によるクラスターの設計を自動化してくれるサービスが提供されている. それが AWS Batch である.

    AWS Batch はその名のとおりバッチ (Batch) 化されたジョブ (入力データだけが異なる独立した演算が繰り返し実行されること) を想定している. 多くの科学計算や機械学習がバッチ計算に当てはまる. たとえば,初期値のパラメータを変えて複数のシミュレーションを走らせる,といったケースだ. AWS Batch を用いることの利点は,クラスターのスケーリングやジョブの割り振りはすべて自動で実行され, ユーザーはクラウドの舞台裏の詳細を気にすることなく,大量のジョブを投入できるシステムが手に入る点である. が,知識として背後では ECS/ASG/EC2 の三つ巴が協調して動作しているという点は知っておいてほしい.

    AWS Batch では,ジョブの投入・管理をスムーズに行うため,次のような概念が定義されている (figure_title). まず, ジョブ (Job) というのが,AWS Batch によって実行される一つの計算の単位である. Job definitions とはジョブの内容を定義するものであり,これには実行されるべき Docker のイメージのアドレスや,割り当てる CPU・RAM の容量,環境変数などの設定が含まれる. Job definition に基づいて個々のジョブが実行される. ジョブが実行されると,ジョブは Job queues に入る. Job queues とは,実行待ち状態にあるジョブの列のことであり,時間的に最も先頭に投入されたジョブが最初に実行される. また,複数の queue を配置し, queue ごとに priority (優先度) を設定することが可能であり, priority の高い queue に溜まったジョブが優先的に実行される (筆者はこれをディズニーランドの"ファストパス"を連想して捉えている). Compute environment とは,先述したクラスターとほぼ同義の概念であり,計算が実行される場所 (EC2 や Fargate からなるクラスター) を指す. Compute environment には,使用する EC2 のインスタンスタイプや同時に起動するインスタンス数の上限などの簡易なスケーリングポリシーが指定されている. Job queues は Compute environment の空き状況を監視しており, それに応じてジョブを Compute environment に投下する.

    以上が AWS Batch を使用するうえで理解しておかなければならない概念であるが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは,実際に自分で手を動かしながら学んでいこう.

    AWS Batch の主要な概念

    EC2 or Fargate?

    ECS でクラスターを構成する際,計算を実行する場として EC2 と Fargate の二つの選択肢があることを説明した. それぞれ長所と短所を抱えているのだが,どのような場合にどちらを使うべきだろうか? それを検討するため,まずは table_title を見てみよう. これは EC2 と Fargate の特徴をまとめたものである. 説明の都合上,大幅な粗視化が行われている点は留意していただきたい.

    EC2 vs Fargate
    EC2Fargate

    Compute capacity

    Medium to large

    Small to medium

    GPU

    Yes

    No

    Launch speed

    Slow

    Fast

    Task placement flexibility

    Low

    High

    Programming complexity

    High

    Low

    これまでに見てきたように, EC2 は最大の CPU 数・メモリーサイズが大きかったり, GPU を利用できたりするなど,単一のインスタンスでの計算能力は高い. 対して, Fargate は単一インスタンスの最大 CPU 数は 4 コアが上限である. その一方で,インスタンスの起動に要する時間は Fargate のほうが圧倒的に早く,より俊敏にクラスターのスケーリングを行うことができる. また,タスクをクラスターに投入する際のフレキシビリティも Fargate のほうが高い. フレキシビリティというのは,例えば一つのインスタンスで 2 つ以上のコンテナを走らせる,などの状況である. 単位 CPU あたりで処理されるタスクの数を最大化する際には,このような設計がしばしば採用される. プログラミングの複雑さという観点からは, Fargate のほうが一般的にシンプルな実装になる.

    このように, EC2 と Fargate は互いに相補的な特性を有しており,アプリケーションによって最適な計算環境は検討される必要がある. また,EC2 と Fargate を両方用いたハイブリッドクラスターというのも定義可能であり,そのような選択肢もしばしば用いられる.

    準備

    ハンズオンのソースコードは GitHub の handson/aws-batch にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,アメリカ東部 (us-east-1) リージョンでは 0.526 $/hour のコストが発生する. 東京 (ap-northeast-1) を選択した場合は 0.71 $/hour のコストが発生する.

    準備 でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, 実践ディープラーニング! MNIST 手書き数字認識タスク で扱った MNIST 手書き文字認識の問題を再度取り上げよう. 実践ディープラーニング! MNIST 手書き数字認識タスク では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    ランダムサーチ法とは,ハイパーパラメータの組をある範囲の中でランダムに抽出し,大量に試行されたランダムな組の中から最適なパラメータの組を見出す方法である. すべての可能性を網羅的に探索できるわけではないが,調整すべきパラメータの数が多数ある場合に,グリッドサーチよりも効率的に広い探索空間をカバーすることができる.

    ベイズ最適化を用いた方法では,過去の探索結果から次にどの組み合わせを探索すべきかという指標を計算し,次に探索するパラメータを決定する. これにより,理論的にはグリッドサーチやランダムサーチ法よりも少ない試行回数で最適なパラメータにたどり着くことができる.

    並列化の観点でいうと,グリッドサーチとランダムサーチは各ハイパーパラメータの組の計算は独立に実行することができるため並列化が容易である. このように独立したジョブとして分割・並列化可能な問題を Embarrassingly parallel な問題とよぶ (直訳すると"恥ずかしいほど並列化可能な問題",ということになる). Embarrassingly parallel な問題はクラウドの強力な計算リソースを用いることで,非常なシンプルな実装で解くことができる. この章ではこのようなタイプの並列計算を取り上げる.

    一方,ベイズ最適化による方法は,過去の結果をもとに次の探索が決定されるので,並列化はそれほど単純ではない. 最近では optuna などのハイパーパラメータ探索のためのライブラリが発達しており,ベイズ最適化の数理的な処理を自動で実行してくれるので便利である. これらのライブラリを使うと,もし一台のコンピュータ (ノード) の中に複数の GPU が存在する場合は,並列に計算を実行することができる. しかしながら,一台のノードにとどまらず,複数のノードをまたいだ並列化は,高度なプログラミングテクニックが必要とされるだけでなく,ノード間の接続様式などクラウドのアーキテクチャにも深く依存するものである. 本書ではここまで高度なクラウドの使用方法には立ち入らない.

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に 実践ディープラーニング! MNIST 手書き数字認識タスク のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    sh
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. Hands-on #2: AWS でディープラーニングを実践 のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    sh
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドでは,--gpus all というパラメータが加わった.

    CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

    (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

    これはオーバーフィッティングとよばれる現象で,ニューラルネットが訓練データに過度に最適化され,訓練データの外のデータに対しての精度 (汎化性能) が向上していないことを示している. このような場合の対処法として, Early stopping とよばれるテクニックが知られている. Early stopping とは,検証データの Loss を追跡し,それが減少から増加に転じるエポックで学習をうち止め,そのエポックでのウェイトパラメータを採用する,というものである. 本ハンズオンでも, Early stopping によって訓練の終了を判断し,モデルの性能評価を行っていく.

    MNIST 手書き文字データセットでは,訓練データとして 60,000 枚,テストデータとして 10,000 枚の画像が与えられている. 本ハンズオンで使用するコードでは,訓練データのうち 80% の 48,000 枚を訓練データとして使用し,残り 20% の 12,000 枚を検証データとして用いている. 詳しくはソースコードを参照のこと.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントは,あるハイパーパラメータの組を指定して Batch にジョブを提出する

    • Batch はジョブを受け取ると, EC2 からなるクラスターで計算を実行する

    • クラスター内では g4dn.xlarge インスタンスが起動する

    • Docker イメージは, AWS 内に用意された ECR (Elastic Container Registry) から取得される

    • 複数のジョブが投下された場合は,その数だけのインスタンスが起動し並列に実行される

    • 各ジョブによる計算の結果は S3 に保存される

    • 最後にクライアントは S3 から結果をダウンロードし,最適なハイパーパラメータの組を決定する

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    python
    class SimpleBatch(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    +
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
    +
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
    +
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
    +
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
    +
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
    +
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    class SimpleBatch(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    +
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
    +
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
    +
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
    +
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
    +
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
    +
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    • で,計算結果を保存するための S3 バケットを用意している

    • で, Compute environment を定義している. ここでは g4dn.xlarge のインスタンスタイプを使用するとし,最大の vCPU 使用数は 64 と指定している. また,最小の vCPU は 0 である. 今回は,負荷がかかっていないときにアイドリング状態にあるインスタンスを用意する利点は全くないので,ここは 0 にするのが望ましい.

    • で, <2> で作成した Compute environment と紐付いた Job queue を定義している.

    • で,ジョブが計算結果を S3 に書き込むことができるよう, IAM ロールを定義している. (IAM とはリソースがもつ権限を管理する仕組みである.詳しくは AWS における権限の管理 (IAM) を参照)

    • では, Docker image を配置するための ECR を定義している.

    • で Job definition を作成している. ここでは,4 vCPU, 12000 MB (=12GB) の RAM を使用するように指定している. また,今後必要となる環境変数 (BUCKET_NAME) を設定している. さらに, <4> で作った IAM を付与している.

    g4dn.xlarge は 1 台あたり 4 vCPU が割り当てられている. このプログラムでは Compute environment の maximum vCPUs を 64 と指定しているので,最大で 16 台のインスタンスが同時に起動することになる. ここで maxium vCPUs を 64 に限定しているのは,なんらかのミスで意図せぬジョブを大量にクラスターに投入してしまった事態で,高額の AWS 利用料金が発生するのを防ぐためである. もし,自分のアプリケーションで必要と判断したならば自己責任において 64 よりも大きな数を設定して構わない.

    ここで注意が一点ある. AWS では各アカウントごとに EC2 で起動できるインスタンスの上限が設定されている. この上限は AWS コンソールにログインし, EC2 コンソールの左側メニューバーの Limits をクリックすることで確認できる (figure_title). g4dn.xlarge (EC2 の区分でいうと G ファミリーに属する) の制限を確認するには, Running On-Demand All G instances という名前の項目を見る. ここにある数字が, AWS によって課されたアカウントの上限であり,この上限を超えたインスタンスを起動することはできない. もし,自分の用途に対して上限が低すぎる場合は,上限の緩和申請を行うことができる. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    EC2コンソールから各種の上限を確認する

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    次に,Job queue overview にある SimpleBatch-queue という項目に注目してほしい. ここでは実行待ちのジョブ・実行中のジョブ・実行が完了したジョブを一覧で確認することができる. PENDING, RUNNING, SUCCEEDED, FAILED などのカラムがあることが確認できる.ジョブが進行するにつれて,ジョブの状態がこのカラムにしたがって遷移していく. 後でジョブを実際にサブミットしたときに戻ってこよう.

    最後に,今回作成した Job definition を確認しよう. 左側のメニューから Job definitions を選択し,次の画面で SimpleBatchjob-definition という項目を見つけて開く. ここから Job definition の詳細を閲覧することができる (figure_title). 中でも重要な情報としては, vCPUs, Memory, GPU がそれぞれ Docker に割り当てられる vCPU・メモリー・ GPU の量を規定している. また, Image と書いてあるところに,ジョブで使用される Docker イメージが指定されている. ここでは, ECR のレポジトリを参照している. 現時点ではこの ECR は空である. 次のステップとして,この ECR にイメージを配置する作業を行おう.

    AWS Batch から Job definition を確認

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン (Hands-on #3: AWS で自動質問回答ボットを走らせる) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    python
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
    +
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
    +
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    • で,新規の ECR を作成している.

    • で Job definition を定義する中で,イメージを <1> で作った ECR から取得するように指定している. これと同時に, Job definition には ECR へのアクセス権限が IAM を通じて自動的に付与される.

    さて,スタックをデプロイした時点では, ECR は空っぽである. ここに自分のアプリケーションで使う Docker イメージを push してあげる必要がある.

    そのために,まずは AWS コンソールから ECR の画面を開こう (検索バーに Elastic Container Registry と入力すると出てくる). Private というタブを選択すると, simplebatch-repositoryXXXXXX という名前のレポジトリが見つかるだろう (figure_title).

    ECR のコンソール画面

    次に,このレポジトリの名前をクリックするとレポジトリの詳細画面に遷移する. そうしたら,画面右上にある View push commands というボタンをクリックする. すると figure_title のようなポップアップ画面が立ち上がる.

    ECR への push コマンド

    このポップアップ画面で表示されている四つのコマンドを順番に実行していくことで,手元の Docker イメージを ECR に push することができる. push を実行する前に, AWS の認証情報が設定されていることを確認しよう. そのうえで,ハンズオンのソースコードの中にある docker/ という名前のディレクトリに移動する. そうしたら,ポップアップ画面で表示されたコマンドを上から順に実行していく.

    ポップアップで表示されるコマンドの 2 つめを見てみると docker build -t XXXXX . となっている. 最後の . が重要で,これは 現在のディレクトリにある Dockerfile を使ってイメージをビルドせよ という意味である. このような理由で, Dockerfile が置いてあるディレクトリに移動する必要がある.

    四つ目のコマンドは,数 GB あるイメージを ECR にアップロードするので少し時間がかかるかもしれないが,これが完了するとめでたくイメージが ECR に配置されたことになる. もう一度 ECR のコンソールを見てみると,確かにイメージが配置されていることが確認できる (figure_title). これで,AWS Batch を使ってジョブを実行させるための最後の準備が完了した.

    ECR へ image の配置が完了した

    単一のジョブを実行する

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    sh
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    python
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
    +
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
    +
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    python
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    python
    # [4]
    +submit_job(0.01, 0.1, 100)
    # [4]
    +submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは AWS CLI のインストール), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    AWS Batch でジョブが実行されている様子

    figure_title で赤で囲った箇所に注目してほしい. 一つのジョブが投入されると,それは SUBMITTED という状態を経て RUNNABLE という状態に遷移する. RUNNABLE とは, ジョブを実行するためのインスタンスが Compute environment に不足しているため,新たなインスタンスが起動されるのを待っている状態に相当する. インスタンスの準備が整うと,ジョブの状態は STARTING を経て RUNNING に至る.

    次に,ジョブのステータスが RUNNING のときの Compute environment の Desired vCPU を見てみよう (figure_title で紫で囲った箇所). ここで 4 と表示されているのは, g4dn.xlarge インスタンス一つ分の vCPU の数である. ジョブの投入に応じて,それを実行するのに最低限必要な EC2 インスタンスが起動されたことが確認できる (興味のある人は, EC2 コンソールも同時に覗いてみるとよい).

    しばらく経つと,ジョブの状態は RUNNING から SUCCEEDED (あるいは何らかの理由でエラーが発生したときには FAILED) に遷移する. 今回のハンズオンで使っている MNIST の学習はだいたい 10 分くらいで完了するはずである. ジョブの状態が SUCCEEDED になるまで見届けよう.

    ジョブが完了すると,学習の結果 (エポックごとの Loss と Accuracy を記録した CSV ファイル) は S3 に保存される. AWS コンソールからこれを確認しよう.

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    python
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    python
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
    +
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
    +
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
    +
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
    +
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
    +
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
    +
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    python
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    python
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    複数のジョブを同時投入したときの Job 一覧

    今度は EC2 コンソールを見てみよう. 左のメニューから Instances を選択すると, figure_title に示すような起動中のインスタンスの一覧が表示される. g4dn.xlarge が 9 台稼働しているのが確認できる. Batch がジョブの投下に合わせて必要な数のインスタンスを起動してくれたのだ!

    複数のジョブを同時投入したときの EC2 インスタンスの一覧

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    python
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
    +
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
    +
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
    +
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
    +
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    今回のパラメータサーチは勉強用に極めて単純化されたものである点は承知いただきたい.

    たとえば,今回は学習率が 0.1 が最も良いとされたが,それは訓練のエポックを 100 に限定しているからかもしれない. 学習率が低いとその分訓練に必要なエポック数も多くなる. 訓練のエポック数をもっと増やせばまた違った結果が観察される可能性はある.

    また,今回は MNIST の訓練データ 60,000 枚のうち, 48,000 枚を訓練データ,残り 12,000 枚を検証データとして用いた. この分割は乱数を固定してランダムに行ったが,もしこの分割によるデータのバイアスを気にするならば, k 個の異なる学習・検証データの分割をあらかじめ用意して,複数回モデルの評価を行う (k-fold cross-validation) 方法も,より精緻なアプローチとして考えられる.

    以上のようにして, CNN を用いた MNIST 分類モデルのハイパーパラメータの最適化の一連の流れを体験した. AWS Batch を利用することで,比較的少ないプログラミングで,動的に EC2 クラスターを制御し,並列にジョブを処理するシステムが構築できた. ここまで EC2 を使いこなすことができれば,多くの問題を自力で解くことが可能になるだろう!

    スタックの削除

    これにて,本ハンズオンは終了である.最後にスタックを削除しよう. 今回のスタックを削除するにあたり,ECR に配置された Docker のイメージは手動で削除されなければならない (これをしないと, cdk destroy を実行したときにエラーになってしまう. これは CloudFormation の仕様なので従うしかない).

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, Hands-on #2: AWS でディープラーニングを実践 で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを Hands-on #3: AWS で自動質問回答ボットを走らせる を参考に構築する.

    実際,本書ではこの流れに沿って演習を進めてきた. MNIST タスクを解くモデルを,最初 Jupyter Notebook を使用して実験し,そのコードをほとんどそのまま Docker にパッケージし, AWS Batch を用いてハイパーパラメータサーチを行った. このサイクルを繰り返すことで,クラウドを最大限に活用した機械学習アプリケーションの開発を進めることができる.

    クラウドを活用した機械学習アプリケーションの開発フロー

    小括

    ここまでが,本書第二部の内容である. 第一部に引き続き盛りだくさんの内容であったが,ついてこれたであろうか?

    第二部ではまず最初に,深層学習の計算をクラウドで実行するため, GPU 搭載型の EC2 インスタンスの起動について解説した. さらに,ハンズオンでは,クラウドに起動した仮想サーバーを使って MNIST 文字認識タスクを解くニューラルネットを訓練した (Hands-on #2: AWS でディープラーニングを実践).

    また,より大規模な機械学習アプリケーションを作るための手段として, Docker と ECS によるクラスターの初歩を説明した (Docker 入門). その応用として,英語で与えられた文章問題への回答を自動で生成するボットをクラウドに展開した (Hands-on #3: AWS で自動質問回答ボットを走らせる). タスクの投入に応じて動的に計算リソースが作成・削除される様子を実際に体験できただろう.

    さらに, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する では AWS Batch を用いてニューラルネットの学習を並列に実行する方法を紹介した. ここで紹介した方法は,ミニマムであるが,計算機システムを大規模化していくためのエッセンスが網羅されている. これらのハンズオン体験から,クラウド技術を応用してどのように現実世界の問題を解いていくのか,なんとなくイメージが伝わっただろうか?

    本書の第三部では,さらにレベルアップし,サーバーレスアーキテクチャという最新のクラウドの設計手法について解説する. その応用として,ハンズオンでは簡単な SNS サービスをゼロから実装する. 引き続きクラウドの最先端の世界を楽しんでいこう!

    Web サービスの作り方

    ここからが,本書第三部の内容になる. これまでのセクションでは,仮想サーバーをクラウド上に起動し,そこで計算を走らせる方法について解説をしてきた. EC2, ECS, Fargate, Batch などを利用して,動的にスケールするクラスターを構成し,並列にタスクを実行するクラウドシステムを実装してきた. 振り返ると,これまで紹介してきた内容は,自分自身が行いたい計算をクラウドを駆使することで実現する,という用途にフォーカスしていたことに気がつくだろう. 一方で,広く一般の人々に使ってもらえるような計算サービス・データベースを提供する,というのもクラウドの重要な役割として挙げられる.

    本章から始まる第三部では,前回までとは少し方向性を変え,どのようにしてクラウド上にアプリケーションを展開し,広く一般の人に使ってもらうか,という点を講義したいと思う. これを通じて,どのようにして世の中のウェブサービスができ上がっているのかを知り,さらにどうやって自分でそのようなアプリケーションをゼロから構築するのか,という点を学んでもらう. その過程で,サーバーレスアーキテクチャという最新のクラウド設計手法を解説する.

    その前準備として,本章ではどのようにしてウェブサービスが出来上がっているのか,その背後にある技術の概要を解説する. 用語の解説が中心となるが,後のハンズオンを実装するために必須の知識であるので,理解して前に進むよう心がけよう.

    ウェブサービスの仕組み  — Twitter を例に

    あなたがパソコンやスマートフォンから Twitter, Facebook, YouTube などのウェブサービスにアクセスしたとき,実際にどのようなことが行われ,コンテンツが提示されているのだろうか?

    HTTP を通じたサーバーとクライアントのデータのやり取りは,すでに知っている読者も多いだろうし,逆にすべて解説しようとすると紙面が足りないので,ここではエッセンスの説明のみにとどめる. 以降では Twitter を具体例として,背後にあるサーバーとクライアントの間の通信を概説しよう. 概念図としては figure_title のような通信がクライアントとサーバーの間で行われていることになる.

    クライアントと Web サーバーの通信の概念図

    前提として,クライアントとサーバーの通信は HTTP (Hypertext Transfer Protocol) を使って行われる. また,最近では,暗号化された HTTP である HTTPS (HTTPS (Hypertext Transfer Protocol Secure)) を用いることがスタンダードになってきている. 第一のステップとして,クライアントは HTTP(S) 通信によってサーバーから静的なコンテンツを取得する. 静的なコンテンツとは, HTML (Hyptertext Markup Language) で記述されたウェブページの文書本体, CSS (Cascading Style Sheets) で記述されたページのデザインやレイアウトファイル,そして JavaScript (JS) で記述されたページの動的な挙動を定義したプログラム,が含まれる. Twitter を含む現代的なウェブアプリケーションの設計では,この静的なファイル群はページの”枠”を定義するだけで,中身となるコンテンツ (例: ツイートの一覧) は別途 API (Application Programming Interface) によって取得されなければならない. そこで,クライアントは先のステップで取得された JavaScript で定義されたプログラムに従って,サーバーに API を送信し,ツイートや画像データを取得する. この際,テキストデータのやり取りには JSON (JavaScript Object Notation) というフォーマットが用いられることが多い. 画像や動画などのコンテンツも同様に API により取得される. このようにして取得されたテキストや画像が,HTML の文書に埋め込まれることで,最終的にユーザーに提示されるページが完成するのである. また,新しいツイートを投稿するときにも,クライアントから API を通じてサーバーのデータベースにデータが書き込まれる.

    REST API

    API (Application Programming Interface) とはこれまで何度も出てきた言葉であるが,ここではよりフォーマルな定義付けを行う. API とはあるソフトウェア・アプリケーションが,外部のソフトウェアに対してコマンドやデータをやり取りするための媒介の一般的総称である. とくに,ウェブサービスの文脈では,サーバーが外界に対して提示しているコマンドの一覧のことを意味する. クライアントは,提示されている API から適切なコマンドを使うことによって,所望のデータを取得したり,あるいはサーバーにデータを送信したりする.

    とくに,ウェブの文脈では REST (Representational State Transfer) とよばれる設計思想に基づいた API が現在では最も一般的に使われている. REST の設計指針に従った API のことを REST API あるいは RESTful API とよんだりする.

    REST API は, figure_title に示したような MethodURI (Universal Resource Identifier) の組からなる.

    REST API

    Method (メソッド) とは,どのような操作を行いたいかを抽象的に表す,"動詞" として捉えることができる. メソッドには HTTP 規格で定義された 9 個の動詞 (verb) を使用することができる. この中でも, GET, POST, PUT, PATCH, DELETE の 5 個が最も頻繁に使用される (table_title). この 5 つのメソッドによる操作を総称して CRUD (create, read, update, and delete) とよぶ.

    REST API Methods
    メソッド意図される動作

    GET

    要素を取得する

    POST

    新しい要素を作成する

    PUT

    既存の要素を新しい要素と置き換える

    PATCH

    既存の要素の一部を更新する

    DELETE

    要素を削除する

    一方, URI は操作が行われる対象,すなわち "目的語" を表す. ウェブの文脈では操作が行われる対象のことをしばしば リソース とよぶ. URI は多くの場合 http または https から始まるウェブサーバーのアドレスから始まり, / (スラッシュ) 以降に所望のリソースのパスが指定される. figure_title の例で言えば, https://api.twitter.com というアドレスの /1.1/status/home_timeline というリソースを取得 (GET) せよ,という意味になる (なお,ここで 1.1 という数字は API のバージョンを示している). この API リクエストによって,ユーザーのホームのタイムラインのツイートの一覧が取得される.

    REST API のメソッドには, table_title で挙げたもの以外に, HTTP プロトコルで定義されているほかのメソッド (OPTIONS, TRACE など) を用いることもできるが,あまり一般的ではない.

    また,これらのメソッドだけでは動詞として表現しきれないこともあるが, URI の名前でより意味を明確にすることもある. メソッドの使い方も,要素を削除する際は必ず DELETE を使わなければならない,という決まりもなく,たとえば, Twitter API でツイートを消す API は POST statuses/destroy/:id で定義されている. 最終的には,各ウェブサービスが公開している API ドキュメンテーションを読んで,それぞれの API がどんな操作をするのかを調べる必要がある.

    REST の概念は 2000 年代初頭に確立され,今日の API 設計のスタンダードとなった. 一方で,ウェブのテクノロジーが進歩するにつれて,新たな API の設計アプローチの需要も高まっている. 近年とくに人気を集めているのが, GraphQL と呼ばれる API の設計方法である. GraphQL は Facebook 社によって最初に作られ,現在は GraghQL Foundation によって維持と更新がされている. GraphQL を使用すると,クライアントは REST と比較してより柔軟性の高いデータのクエリを行うことができるなど,いくつかの利点がある. キーワードだけでも知っておくと,今後役に立つだろう.

    Twitter API

    もう少し具体的にウェブサービスの API を体験する目的で,ここでは Twitter の API を見てみよう. Twitter が提供している API の一覧は Twitter の Developer Documentation で見ることができる. いくつかの代表的な API を table_title にまとめた.

    Twitter API
    エンドポイント動作

    GET statuses/home_timeline

    ホームのタイムラインのツイートの一覧を取得する.

    GET statuses/show/:id

    :id で指定されたツイートの詳細情報を取得する.

    GET search

    ツイートの検索を実行する.

    POST statuses/update

    新しいツイートを投稿する.

    POST media/upload

    画像をアップロードする

    POST statuses/destroy/:id

    :id で指定されたツイートを削除する.

    POST statuses/retweet/:id

    :id で指定されたツイートをリツイートする.

    POST statuses/unretweet/:id

    :id で指定されたツイートのリツイートを取り消す.

    POST favorites/create

    選択したツイートを"いいね"する.

    POST favorites/destroy

    選択したツイートを"いいね"を取り消す.

    この API リストをもとに, Twitter のアプリまたはウェブサイトを開いたときに起こるクライアントとサーバーの通信をシミュレートしてみよう.

    ユーザーが Twitter を開くと,まず最初に GET statuses/home_timeline の API リクエストによって,ユーザーのホームのタイムラインのツイートのリストが取得される. 個々のツイートは JSON 形式のデータになっており, id, text, user, coordinates, entities などの属性を含む. id はツイートに固有な ID を表し, text はツイートの本文を含んでいる. user はツイートを投稿したユーザーの名前やプロフィール画像の URL などを含んだ JSON データになっている. coordinates にはツイートが発信された地理的な座標が記録されている. また, entities にはツイートに関連するメディアファイル (画像など) のリンクなどの情報が埋め込まれている. GET statuses/home_timeline からは直近のツイートのリスト (リストが長すぎる場合は途中で切られたもの) が取得される. もしツイートの ID を知っている場合は GET statuses/show/:id を呼ぶことによって, :id パラメータで指定された特定のツイートを取得することができる.

    ツイートの検索を行うためには GET search API を使用する. この API には,ツイートに含まれる単語や,ハッシュタグ,ツイートの発信された日時や場所など,様々なクエリの条件を渡すことができる. API からは, GET statuses/home_timeline などと同様, JSON 形式のツイートのデータが返される.

    ユーザーが新しいツイートを投稿するには POST statuses/update のエンドポイントを利用する. POST statuses/update には,ツイートの文章や,リプライの場合はリプライ先のツイートの ID などのデータを送信する. また,ツイートに画像データを添付したい場合は, POST media/upload を併せて使用する. ツイートの削除を行うには, POST statuses/destroy/:id を用いる.

    そのほか,頻繁に行われる操作としては, POST statuses/retweet/:idPOST statuses/unretweet/:id がある. これらは, :id で指定されるツイートに対して,それぞれリツイートを実行あるいは取り消すための API である. また, POST favorites/createPOST favorites/destroy を使用することによって,選択されたツイートに"いいね"を追加したり,取り消したりする操作を行う.

    このような一連の操作が, Twitter のアプリの背後では行われている. また,自分自身でボットを作成したい場合は,これらの API を適切に組み合わせ,カスタムのプログラムを書くことで実現される.

    このように, API はあらゆるウェブサービスを作るうえで一番基礎となる要素である. 次からの章では本章で紹介した用語が何度も出てくるので,頭の片隅に置いたうえで読み進めていただきたい.

    Serverless architecture

    サーバーレスアーキテクチャ (Serverless architecture) あるいは サーバーレスコンピューティング (Serverless computing) とは,従来とは全く異なるアプローチに基づくクラウドシステムの設計方法である. 歴史的には, AWS が 2014 年に発表した Lamba がサーバーレスアーキテクチャの先駆けとされている. その後, Google や Microsoft などのクラウドプラットフォームも同様の機能の提供を開始している. サーバーレスアーキテクチャの利点は,スケーラブルなクラウドシステムを安価かつ簡易に作成できる点であり,近年いたるところで導入が進んでいる.

    Serverless とは,文字どおりの意味としてはサーバーなしで計算をするということになるが,それは一体どういう意味だろうか? サーバーレスについて説明するためには,まずは従来的な, "serverful" とよばれるようなシステムについて解説しなければならない.

    Serverful クラウド (従来型)

    従来的なクラウドシステムのスケッチを figure_title に示す. クライアントから送信されたリクエストは,最初に API サーバーに送られる. API サーバーでは,リクエストの内容に応じてタスクが実行される. タスクには,API サーバーだけで完結できるものもあるが,多くの場合,データベースの読み書きが必要である. データベースには,データベース専用の独立したサーバーマシンが用いられることが一般的である. また,画像や動画などの容量の大きいデータは,また別のストレージサーバーに保存されることが多い. これらの API サーバー,データベースサーバー,ストレージサーバーはそれぞれ独立したサーバーマシンであり, AWS の言葉では EC2 による仮想インスタンスを想定してもらったらよい.

    多くのウェブサービスでは,多数のクライアントからのリクエストを処理するため,複数のサーバーマシンがクラウド内で起動し,負荷を分散するような設計がなされている. クライアントから来たリクエストを計算容量に余裕のあるサーバーに振り分けるような操作を Load balancing とよび,そのような操作を担当するマシンのことを Load balancer という.

    計算負荷を分散する目的で多数のインスタンスを起動するのはよいのだが,計算負荷が小さすぎてアイドリング状態にあるようではコストと電力の無駄遣いである. したがって,すべてのサーバーが常に目標とする計算負荷を維持するよう,計算の負荷に応じてクラスター内の仮想サーバーの数を動的に増減させるような仕組みが必要である. そのような仕組みをクラスターのスケーリングとよび,負荷の増大に応答して新しい仮想インスタンスをクラスターに追加する操作を scale-out,負荷の減少に応答してインスタンスをシャットダウンする操作を scale-in とよぶ. クラスターのスケーリングは, API サーバーではもちろんのこと,データベースサーバー・ストレージサーバーでも必要になる. ストレージサーバーでは,例えば頻繁にアクセスされるデータはキャッシュ領域に保存したり,データのコピーを複数作るなどのスケーリングが行われる. データベースサーバーも同様に,頻繁にアクセスされるデータのアクセスがパンクしてしまわないよう,分散的な処理が必要となる. このように,クラウドシステム内すべての箇所で,負荷が均一になるような調整が必要であり,開発者は多くの時間をそのチューニングに費やさなければならない. また,サービスの利用者の数などに応じてスケーリングの設定は常に見直される必要があり,継続的な開発が要求される.

    さらに問題を複雑にするのは,API サーバーで処理されるべきタスクが,非一様な点である. 非一様であるとは,たとえばタスク A は 3000 ミリ秒の実行時間と 512MB のメモリーを消費し,別のタスク B は 1000 ミリ秒の実行時間と 128MB のメモリーを消費する,というような状況を指している. 一つのサーバーマシンが計算負荷が異なる複数のタスクを処理する場合,クラスターのスケーリングはより複雑になる. この状況をシンプルにするために,1サーバーで実行するタスクは1種類に限る,という設計も可能であるが,そうするとで生まれる弊害も多い (ほとんど使われないタスクに対してもサーバー一台をまるまる割り当てなければならない = ほとんどアイドリング状態になってしまう,など).

    Serverful なクラウドシステム

    Serverless クラウドへ

    Serverful クラウド (従来型) で議論したように,クラスターのスケーリングはクラウドシステムの経済的効率とシステムの安定性を最大化するために必須の作業である. それを反映して,多くの開発者の時間が投資されてきた.

    クラスターのスケーリングはすべての開発者が何度も繰り返し行ってきた作業であり,いくつかの側面をテンプレート化し,共通化することができたならば開発のコストを大幅に削減できるだろう. それを実現するには,根本的なレベルからクラウドシステムの設計を考え直す必要がある. スケーリングを前提として考えることで,もっとシンプルで見通しがよいクラウドシステムの設計の仕組みはないだろうか? そのような動機が,サーバーレスアーキテクチャが誕生する背後にあった.

    従来の serverful なシステムでの最大の問題点は,サーバーをまるまる占有してしまうという点にある. すなわち, EC2 インスタンスを起動したとき,そのインスタンスは起動したユーザーだけが使えるものであり,計算のリソース (CPU や RAM) が独占的に割り当てられた状態になる. 固定した計算資源の割り当てがされてしまっているので,インスタンスの計算負荷が 0%であろうが 100%であろうが,均一の使用料金が起動時間に比例して発生する.

    サーバーレスアーキテクチャは,このような 独占的に割り当てられた計算リソースというものを完全に廃止することを出発点とする. サーバーレスアーキテクチャでは,計算のリソースは,クラウドプロバイダーがすべて管理する. クライアントは,仮想インスタンスを一台まるごと借りるのではなく,計算のタスクの需要が生まれる毎に,実行したいプログラム・コマンドをクラウドに提出する. クラウドプロバイダーは,自身のもつ巨大な計算リソースから空きを探し,提出されたプログラムを実行し,実行結果をクライアントに返す. 言い換えると,計算リソースのスケーリングやアロケーションなどはクラウドプロバイダーが一手に引き受け,ユーザーはジョブをサブミットすることに注力する,という枠組みである. これを図示すると, figure_title のようになる.

    従来のクラウドと Serverless クラウドの比較

    サーバーレスクラウドでは,スケーリングはすべてクラウドプロバイダーが引き受けるので,スケーラビリティーが保証されている. クライアントが同時に大量のタスクを送信した場合でも,クラウドプロバイダー側の独自の仕組みによってすべてのタスクが遅延なく実行される. また,サーバーレスクラウドを利用することで,クラウドのコストは実際に使用した計算の総量 (稼働時間) で決定されることになる. これは,計算の実行総量に関わらずインスタンスの起動時間で料金が決定されていた従来のシステムと比べて大きな違いである.

    サーバーレスクラウドは,従来のクラウドとは根本から異なったアプローチなので,コードの書き方やシステムの設計が大きく異なる. サーバーレスクラウドを開発・運用するには,サーバーレス固有の概念や用語に精通している必要がある. 以降では,実際にクラウドを動かしながら,サーバーレスをより具体的に体験していこう.

    従来型の(仮想インスタンスをたくさん起動するような)クラウドシステムは,賃貸と似ているかもしれない. 部屋を借りるというのは,その部屋でどれだけの時間を過ごそうが,月々の家賃は一定である. 同様に,仮想サーバーも,それがどれほどの計算を行っているかに関わらず,一定の料金が時間ごとに発生する.

    一方で,サーバーレスクラウドは,電気・水道・ガス料金 と似ている. こちらは,実際に使用した量に比例して料金が決定されている. サーバーレスクラウドも,実際に計算を行った総時間で料金が決まる仕組みになっている.

    サーバーレスクラウドを構成するコンポーネント

    サーバーレスアーキテクチャの概要がわかってきたところで,ここでは AWS においてサーバーレスクラウドを構成する様々なコンポーネントを紹介していこう. 特に, Lambda, S3, DynamoDB を取り上げ,解説する (figure_title). サーバーレスクラウドは,これらのコンポーネントを統合することで一つのシステムが出来上がる. ここでは, Lambda,S3,DynamoDB を利用する際に押さえておかなければならない知識を一通り説明しきる都合上,具体的なイメージがわきにくいかもしれない. が,続く Hands-on #5: サーバーレス入門 でそれぞれについてハンズオン形式で演習を行うので,そこでさらに理解を深めれば大丈夫である.

    Lambda, S3, DynamoDB のアイコン

    Lambda

    AWS でサーバーレスコンピューティングの中心を担うのが, Lambda である. Lambda の使い方を figure_title に図示している. Lambda の仕組みはシンプルで,まずユーザーは実行したいプログラムのコードを事前に登録しておく. プログラムは, Python, Node.js, Ruby などの主要な言語がサポートされている. Lambda に登録されたひとつひとつのプログラムを関数 (Function) とよぶ. そして,関数を実行したいときに,invoke コマンドを Lambda に送信する. Lambda では, invoke のリクエストを受け取るとただちに (数ミリセカンドから数百ミリセカンド程度の時間で) プログラムの実行を開始する. そして,実行結果をクライアントやその他の計算機に返す.

    AWS Lambda

    このように,Lambda では占有された仮想インスタンスは存在せず,実行を待っているプログラムだけがある状態である. invoke のリクエストに応じて,プログラムが AWS の巨大な計算機プールのどこかに配置され,実行される. 同時に複数のリクエストが来た場合でも, AWS はそれらを実行するための計算リソースを割り当て,並列的に処理を行ってくれる. 原理上は,数千から数万のリクエストが同時に来たとしても, Lambda はそれらを同時に実行することができる. このような,占有された仮想サーバーの存在なしに,動的に関数を実行するサービスのことを総称して FaaS (Function as a Service) とよぶ.

    Lambda ではそれぞれの関数につき, 128MB から 10240MB のメモリーを使用することができる (執筆時点の仕様). また,実効的な CPU のパワーはメモリーの量に比例する形で割り当てられる. すなわち,タスクに割り当てたメモリーの量が多ければ多いほど,より多くの CPU リソースが割り当てられることになる (しかし, RAM と CPU パワーの具体的な換算表は AWS からは公開されていない). 実行時間は 100 ミリ秒の単位で記録され,実行時間に比例して料金が決定される. table_title は Lambda の利用料金表である (執筆時点で ap-north-east1 リージョンを選択した場合).

    Lambda の料金表
    Memory (MB)Price per 100ms

    128

    $0.0000002083

    512

    $0.0000008333

    1024

    $0.0000016667

    3008

    $0.0000048958

    実行時間に比例する料金に追加して,リクエストを送信するごとに発生する料金が設定されている. これは,百万回のリクエストにつき $0.2 である. たとえば, 128MB のメモリーを使用する関数を,それぞれ 200 ミリ秒,合計で 100 万回実行した場合, 0.0000002083 * 2 * 10^6 + 0.2 = $0.6 の料金となる. ウェブサーバーのデータベースの更新など簡単な計算であれば,200 ミリ秒程度で実行できる関数も多いことから,100 万回データベースの更新を行ったとしても,たった $0.6 しかコストが発生しないことになる. また,コードが実行されず待機状態になっている場合は,発生する料金は 0 である. このように,実際に意味のある処理が行われた時間にのみ,料金が発生する仕組みになっている.

    Lambda は比較的短時間で完了する,反復性の高いタスクの実行に向いている. データベースの読み書きはその典型的な例であるが,そのほかにも,画像のサイズをトリミングしたり,サーバーサイドで定期的に実行されるメンテナンス処理などの利用が考えられる. また,複数の Lambda をリレー式に繋げることも可能で,シンプルな処理を組み合わせることで複雑なロジックを表現することができる.

    上述の Lambda の料金計算は,説明のためコストに寄与する要素をいくつか省いている点は承知いただきたい. 例えば, DynamoDB の読み書きに関する料金や,ネットワークの通信にかかわるコストが考慮されていない.

    サーバーレスストレージ: S3

    サーバーレスの概念は,ストレージにも拡張されている.

    従来的なストレージ (ファイルシステム) では,必ずホストとなるマシンと OS が存在しなければならない. したがって,それほどパワーは必要ないまでも,ある程度の CPU リソースを割かなければならない. また,従来的なファイルシステムでは,データ領域のサイズは最初にディスクを初期化するときに決めなければならず,後から容量を増加させることはしばしば困難である (ZFS などのファイルシステムを使えばある程度は自由にファイルシステムのサイズを変更することは可能である). よって,従来的なクラウドでは,ストレージを借りる際にはあらかじめディスクのサイズを指定せねばならず,ディスクの中身が空であろうと満杯であろうと,同じ利用料金が発生することになる (figure_title).

    Simple Storage Service (S3) は,サーバーレスなストレージシステムを提供する (figure_title). S3 は従来的なストレージシステムと異なり, OS に"マウントする”という概念はない. 基本的に API を通じてデータの読み書きの操作が行われる. また,データの冗長化や暗号化,バックアップの作成など,通常ならば OS と CPU が介在しなければならない操作も, API を通じて行うことができる. S3 では事前に決められたディスク領域のサイズはなく,データを入れれば入れた分だけ,保存領域は拡大していく (仕様上はペタバイトスケールのデータを保存することが可能である). ストレージにかかる料金は,保存してあるデータの総容量で決定される.

    S3 と従来的なファイルシステムの比較

    S3 を利用する際に,料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 説明のため主要な事項のみ取り出している. 詳細は 公式ドキュメンテーション "Amazon S3 pricing" を参照).

    S3 の利用料金
    項目料金

    Data storage (First 50TB)

    $0.023 per GB per month

    PUT, COPY, POST, LIST requests (per 1,000 requests)

    $0.005

    GET, SELECT, and all other requests (per 1,000 requests)

    $0.0004

    Data Transfer IN To Amazon S3 From Internet

    $0

    Data Transfer OUT From Amazon S3 To Internet

    $0.09 per GB

    第一に,データの保存には $0.025 per GB のコストが月ごとに発生する. したがって,1000GB のデータを S3 に一ヵ月保存した場合, $25 の料金が発生することになる. また,PUT, COPY, POST などのリクエスト (=データを書き込む操作) に対しては,データ容量に関係なく,1000 回ごとに $0.005 のコストが発生する. GET, SELECT などのリクエスト (=データを読み込む操作) に対しては,1000 回ごとに $0.0004 のコストが発生する. また, S3 はデータを外に取り出す際の通信にもコストが生じる. 執筆時点では,S3 からインターネットを通じて外部にデータを転送 (data-out) すると $0.09 per GB のコストが発生する. データをインターネットを通じて S3 に入れる (data-in) 通信は無料で行える. また, AWS の 同じ Region 内のサービス (Lambda や EC2 など) にデータを転送するのは無料である. AWS のリージョンをまたいだデータの転送にはコストが発生する. いずれにせよ,サーバーレスの概念に則り,すべての料金が従量課金制で決定される設定になっている.

    サーバーレスデータベース: DynamoDB

    サーバーレスの概念は,データベースにも適用することができる.

    ここでいうデータベースとは, Web サービスなどにおけるユーザーや商品の情報を記録しておくための保存領域のことを指している. 従来的に有名なデータベースとしては MySQL, PostgreSQL, MongoDB などが挙げられる. データベースと普通のストレージの違いは,データの検索機能にある. 普通のストレージではデータは単純にディスクに書き込まれるだけだが, データベースでは検索がより効率的になるようなデータの配置がされたり, 頻繁にアクセスされるデータはメモリーにキャッシュされるなどの機能が備わっている. これにより,巨大なデータの中から,興味のある要素を高速に取得することができる.

    このような検索機能を実現するには,当然 CPU の存在が必須である. したがって,従来的なデータベースを構築する際は,ストレージ領域に加えて,たくさんの CPU コアを搭載したマシンが用いられることが多い. また,データベースが巨大な場合は複数マシンにまたがった分散型のシステムが設計される. 分散型システムの場合は, Serverful クラウド (従来型) で議論したようにデータベースへのアクセス負荷に応じて適切なスケーリングがなされる必要がある.

    DynamoDB は, AWS が提供しているサーバーレスな分散型データベースである. サーバーレスであるので,占有されたデータベース用仮想インスタンスは存在せず, API を通じてデータの書き込み・読み出し・検索などの操作を行う. S3 と同様に,データ保存領域の上限は定められておらず,データを入れれば入れた分だけ,保存領域は拡大していく. また,データベースへの負荷が増減したときのスケーリングは, DynamoDB が自動で行うので,ユーザーは心配する必要はない.

    DynamoDB での利用料金の計算はやや複雑なのだが, "On-demand Capacity" というモードで使用した場合の料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 詳細は 公式ドキュメンテーション "Pricing for On-Demand Capacity" を参照).

    DynamoDB の利用料金
    項目料金

    Write request units

    $1.25 per million write request units

    Read request units

    $0.25 per million read request units

    Data storage

    $0.25 per GB-month

    DynamoDB ではデータの書き込み操作の単位を write request unit とよび,データの読み込み操作の単位を read request unit とよぶ. 基本的に, 1kB 以下のデータを一度書き込むと 1 write request unit を消費し,4kB 以下のデータを一度読み込むと 1 read request unit を消費する (詳しくは 公式ドキュメンテーション "Read/Write Capacity Mode" を参照のこと). write request units は 100 万回ごとに $1.25, read request units は 100 万回ごとに $0.25 のコストが設定されている. また,保存されたデータ容量に対して $0.25 per GB のコストが月ごとに発生する. DynamoDB は高速な検索機能などを備えたデータベースであるので, GB あたりのストレージコストは S3 に比べ 10 倍程度高い. DynamoDB のデータの転送に関わるコストは,同じリージョン内ならば data-in,data-out ともに $0 である. リージョンをまたいだ通信には別途コストが発生する.

    その他のサーバーレスクラウドの構成要素

    以上で紹介した Lambda, S3, DynamoDB がサーバーレスクラウドの中で最も使用する頻度が高いサービスになる. その他のサーバーレスクラウドの構成要素を以下に列挙する. いくつかについては,今後のハンズオンを行う中で改めて解説を行う.

    サーバーレスアーキテクチャは万能か?

    この問いへの答えは,筆者は NO であると考える.

    ここまで,サーバーレスの利点を強調して説明をしてきたが,まだまだ新しい技術なだけに,欠点,あるいはサーバーフルなシステムに劣る点は数多くある.

    大きな欠点を一つあげるとすれば,サーバーレスのシステムは各クラウドプラットフォームに固有なものなので,特定のプラットフォームでしか運用できないシステムになってしまう点であろう. AWS で作成したサーバーレスのシステムを, Google のクラウドに移植するには,かなり大掛かりなプログラムの書き換えが必要になる. 一方, serverful なシステムであれば,プラットフォーム間のマイグレーションは比較的簡単に行うことができる. クラウドプロバイダーとしては,自社のシステムへの依存度を強めることで,顧客を離さないようにするという狙いがあるのだろう…

    その他,サーバーレスコンピューティングの欠点や今後の課題などは,次の論文で詳しく議論されている. 興味のある読者はぜひ読んでいただきたい.

    Hands-on #5: サーバーレス入門

    前章ではサーバーレスアーキテクチャの概要の説明を行った. 本章では,ハンズオン形式でサーバーレスクラウドを実際に動かしながら,具体的な使用方法を学んでいこう. 今回のハンズオンでは Lambda, S3, DynamoDB の三つのサーバーレスクラウドの構成要素に触れていく. それぞれについて,短いチュートリアルを用意してある.

    Lambda ハンズオン

    まずは, Lambda を実際に動かしてみよう. ハンズオンのソースコードは GitHub の handson/serverless/lambda に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して Python で書かれたコードを Lambda に登録する. 続いて STEP 2 では, Invoke API を使用して,同時にいくつもの Lambda を起動し,並列な計算を行う. Lambda のワークフローを体験する目的で最小限の設定である.

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    py
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
    +
    +class SimpleLambda(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
    +
    +class SimpleLambda(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

    • 次に, Lambda に <1> で書いた関数を配置している. パラメータの意味は,文字どおりの意味なので難しくはないが,以下に解説する.

      • runtime=_lambda.Runtime.PYTHON_3_7: ここでは, Python3.7 を使って上記で定義された関数を実行せよ,と指定している. Python3.7 のほかに, Node.js, Java, Ruby, Go などの言語を指定することが可能である.

      • code=_lambda.Code.from_inline(FUNC): 実行されるべき関数が書かれたコードを指定する. ここでは, FUNC=... で定義した文字列を渡しているが,文字列以外にもファイルのパスを渡すことも可能である.

      • handler="index.handler": これは,コードの中にいくつかのサブ関数が含まれているときに,メインとサブを区別するためのパラメータである. handler という名前の関数をメイン関数として実行せよ,という意味である.

      • memory_size=128: メモリーは 128MB を最大で使用することを指定している.

      • timeout=core.Duration.seconds(10) タイムアウト時間を 10 秒に設定している. 10 秒以内に関数の実行が終了しなかった場合,エラーが返される.

      • dead_letter_queue_enabled=True: アドバンストな設定なので説明は省略する.

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    Lambda コンソール - 関数の一覧

    今回のアプリケーションで作成したのが SimpleLambda で始まるランダムな名前のついた関数だ. 関数の名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. 先ほどプログラムの中で定義した Python の関数がエディターから確認できる. さらに下の方にスクロールすると,関数の各種設定も確認できる.

    Lambda コンソール - 関数の詳細

    Lambda で実行されるコードは, Lambda のコンソール画面 (figure_title) のエディターで編集することもできる. デバッグをするときなどは,こちらを直接いじる方が早い場合もある. その場合は, CDK のコードに行った編集を反映させなおすことを忘れずに.

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    sh
    ....................................................................................................
    +Submitted 100 tasks to Lambda!
    ....................................................................................................
    +Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    figure_title で "Invocations" が関数が何度実行されたかを意味している. たしかに 100 回実行されていることがわかる. さらに, "Concurrent executions" は何個のタスクが同時に行われたかを示している. ここでは 96 となっていることから,96 個のタスクが並列的に実行されたことを意味している (これが 100 とならないのは,タスクの開始のコマンドが送られたのが完全には同タイミングではないことに起因する).

    このように,非常にシンプルではあるが, Lambda を使うことで,同時並列的に処理を実行することのできるクラウドシステムを簡単に作ることができた.

    もしこのようなことを従来的な serverful なクラウドで行おうとした場合,クラスターのスケーリングなど多くのコードを書くことに加えて,いろいろなパラメータを調節する必要がある.

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • partition_key: すべての DynamoDB テーブルには Partition key が定義されていなければならない. Partition key とは,テーブル内の要素 (レコード) ごとに存在する固有の ID のことである. 同一の Partition key をもった要素がテーブルの中に二つ以上存在することはできない (注: Sort Key を使用している場合は除く.詳しくは 公式ドキュメンテーション "Core Components of Amazon DynamoDB" 参照). また, Partition key が定義されていない要素はテーブルの中に存在することはできない. ここでは, Partition key に item_id という名前をつけている.

    • billing_mode: ddb.BillingMode.PAY_PER_REQUEST を指定することで, On-demand Capacity Mode の DynamoDB が作成される. ほかに PROVISIONED というモードがあるが,これはかなり高度なケースを除いて使用しないだろう.

    • removal_policy: CloudFormation のスタックが消去されたときに, DynamoDB も一緒に消去されるかどうかを指定する. このコードでは DESTROY を選んでいるので,すべて消去される. ほかのオプションを選択すると,スタックを消去しても DynamoDB のバックアップを残す,などの動作を定義することができる.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    DynamoDB のコンソール (テーブルの一覧)

    今回のアプリケーションで作成したのが SimpleDynamoDb で始まるランダムな名前のついたテーブルだ. テーブルの名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. "Items" のタブをクリックすると,テーブルの中のレコードを確認できる. 現時点ではなにもデータを書き込んでいないので,空である.

    DynamoDB のコンソール (テーブルの詳細画面)

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    python
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
    +
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
    +
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    python
    import boto3
    +ddb = boto3.resource('dynamodb')
    +
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)
    import boto3
    +ddb = boto3.resource('dynamodb')
    +
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    python
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if key is None:
    +        key = os.path.basename(filename)
    +
    +    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if key is None:
    +        key = os.path.basename(filename)
    +
    +    bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    python
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if filename is None:
    +        filename = os.path.basename(key)
    +
    +    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if filename is None:
    +        filename = os.path.basename(key)
    +
    +    bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #6: Bashoutter

    さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

    ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

    準備

    ハンズオンのソースコードは GitHub の handson/bashoutter に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. それ以外に必要な準備はない.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行できる.

    アプリケーションの説明

    API

    今回のアプリケーションでは,人々からの俳句の投稿を受け付けたり,投稿された俳句の一覧を取得する,といった機能を実装したい. この機能を実現するための最小限の設計として, table_title に示すような四つの REST API を今回は実装する. 俳句を投稿する,閲覧する,削除するという基本的なデータ操作を行うための API が完備されている. また, PATCH /haiku/{item_id} は, {item_id} で指定された俳句に”いいね”をするために使用する.

    Bashoutter API

    GET /haiku

    俳句の一覧を取得する

    POST /haiku

    新しい俳句を投稿する

    PATCH /haiku/{item_id}

    {item_id} で指定された俳句にお気に入り票を一つ入れる

    DELETE /haiku/{item_id}

    {item_id} で指定された俳句を削除する

    それぞれの API のパラメータおよび返り値の詳細は,ハンズオンのソースコードの中の swagger.yml に定義してある.

    Open API Specification (OAS; 少し前は Swagger Specification とよばれていた) は, REST API のための記述フォーマットである. OAS に従って API の仕様が記述されていると,簡単にドキュメンテーションを生成したり,クライアントアプリケーションを自動生成することができる. 今回用意した API 仕様 も, OAS に従って書いてある. 詳しくは Swagger の公式ドキュメンテーション などを参照.

    アプリケーションアーキテクチャ

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#5で作製するアプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントからの API リクエストは, API Gateway (後述)にまず送信され, API の URI で指定された Lambda 関数へ転送される.

    • それぞれの API のパス (リソース) ごとに独立した Lambda を用意する.

    • 俳句の情報 (作者,本文,投稿日時など) を記録するためのデータベース (DynamoDB) を用意する.

    • 各 Lambda 関数には, DynamoDB へのアクセス権を付与する.

    • 最後に,ウェブブラウザからコンテンツを表示できるよう, ウェブページの静的コンテンツを配信するための S3 バケットを用意する.クライアントはこの S3 バケットにアクセスすることで HTML/CSS/JS などのコンテンツを取得する.

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    python
    class Bashoutter(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
    +
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
    +
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
    +
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
    +
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
    +
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    class Bashoutter(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
    +
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
    +
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
    +
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
    +
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
    +
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

    • 静的コンテンツを配信するための S3 バケットを用意している.

    • それぞれの API で実行される Lambda 関数を定義している. 関数は Python3.7 で書かれており,コードは handson/bashoutter/api/api.py にある.

    • <3> で定義された Lambda 関数に対し,データベースへの読み書きのアクセス権限を付与している.

    • ここで,API Gateway により,各 API パスとそこで実行されるべき Lambda 関数を紐付けている.

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    python
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    今回のハンズオンでは説明の簡略化のため CloudFront の設定を行わなかったが,興味のある読者は次のリンクのプログラムが参考になるだろう.

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    python
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    python
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
    +
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
    +
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
    +
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
    +
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    python
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    そのような理由により,このコードでは GET のハンドラー関数に対しては grant_read_data() によって, read 権限のみを付与している.

    API Gateway

    API Gateway とは, API の"入り口"として,API のリクエストパスに従って Lambda や EC2 などに接続を行うという機能を担う (figure_title). Lambda や EC2 によって行われた処理の結果は,再び API Gateway を経由してクライアントに返される. このように,クライアントとバックエンドサーバーの間に立ち, API のリソースパスに応じて接続先を振り分けるようなサーバーをルーター,あるいはリバースプロキシとよんだりする. 従来的には,ルーターにはそれ専用の仮想サーバーが置かれることが一般的であった. しかし, API Gateway はサーバーレスなルーターとして,固定されたサーバーを配置することなく, API のリクエストが来たときのみ起動し,API のルーティングを実行する. サーバーレスであることの当然の帰結として,アクセスの件数が増大したときにはそれにルーティングの処理能力を自動で増やす機能も備わっている.

    API Gateway

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    python
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
    +
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
    +
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
    +
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
    +
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

    • 次に, api.root.add_resource() のメソッドを呼ぶことで, /haiku という API パスを追加している.

    • 続いて, add_method() を呼ぶことで, GET, POST のメソッドを /haiku のパスに定義している.

    • さらに, haiku.add_resource("{item_id}") により, /haiku/{item_id} という API パスを追加している.

    • 最後に, add_method() を呼ぶことにより, PATCH, DELETE のメソッドを /haiku/{item_id} のパスに定義している.

    このように, API Gateway の使い方は非常にシンプルで,逐次的に API パスとそこで実行されるメソッド・Lambda を記述していくだけでよい.

    このプログラムで 新規 API を作成すると, ランダムな URL がその API のエンドポイントとして割り当てられる. これを. api.example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    API Gateway コンソール画面 (1)

    今回デプロイした "BashoutterApi" という名前の API をクリックすることで figure_title のような画面に遷移し,詳細情報を閲覧できる. GET /haiku, POST /haiku などが定義されていることが確認できる.

    それぞれのメソッドをクリックすると,そのメソッドの詳細情報を確認できる. API Gateway は,前述したルーティングの機能だけでなく,認証機能などを追加することも可能である. このハンズオンではとくにこれらの機能は使用しないが, "Method Request" と書いてある項目などがそれに相当する. 次に, figure_title で画面右端の赤色で囲った部分に,この API で呼ばれる Lambda 関数が指定されていることに注目しよう. 関数名をクリックと,該当する Lambda のコンソールに遷移し,関数の中身を閲覧することが可能である.

    API Gateway コンソール画面 (2)

    次に, S3 のコンソール画面に移ってみよう. bashouter- で始まるランダムな名前のバケットが見つかるはずである (figure_title).

    S3 コンソール画面

    バケットの名前をクリックすることで,バケットの中身を確認してみよう. index.html のほか, css/, js/ などのディレクトリがあるのが確認できるだろう (figure_title). これらが,ウェブページの"枠"を定義している静的コンテンツである.

    S3 バケットの中身

    API リクエストを送信する

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    $ http GET "\${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    sh
    $ http POST "\${ENDPOINT_URL}/haiku" \\
    +username="松尾芭蕉" \\
    +first="閑さや" \\
    +second="岩にしみ入る" \\
    +third="蝉の声"
    $ http POST "\${ENDPOINT_URL}/haiku" \\
    +username="松尾芭蕉" \\
    +first="閑さや" \\
    +second="岩にしみ入る" \\
    +third="蝉の声"

    次のような出力が得られるだろう.

    sh
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    +
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]
    $ http GET "\${ENDPOINT_URL}/haiku"
    +
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    sh
    $ http PATCH "\${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "\${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]
    $ http GET "\${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    sh
    $ http DELETE "\${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "\${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている (figure_title 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    ウェブブラウザを開き,アドレスバーに S3 の URL を入力しへアクセスしてみよう. すると, figure_title のようなページが表示されるはずである.

    "Bashoutter" の GUI 画面

    ページが表示されたら,一番上の "API Endpoint URL" と書いてあるテキストボックスに,今回デプロイした API Gateway の URL を入力する (今回のアプリケーションでは,API Gateway の URL はランダムに割り当てられるのでこのような GUI の仕様になっている). そうしたら,画面の "REFRESH" と書いてあるボタンを押してみよう. データベースに俳句が登録済みであれば,俳句の一覧が表示されるはずである. 各俳句の左下にあるハートのアイコンをクリックすることで, "like" の票を入れることができる.

    新しい俳句を投稿するには,五七五と投稿者の名前を入力して, "POST" を押す. "POST" を押した後は,再び "REFRESH" ボタンを押すことで最新の俳句のリストをデータベースから取得する.

    アプリケーションの削除

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. Hands-on #5: サーバーレス入門 では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    これらの演習を通じて,世の中のウェブサービスがどのようにしてでき上がっているのか,少し理解が深まっただろうか? また,そのようなウェブアプリケーションを自分が作りたいと思ったとき,今回のハンズオンがその出発点となることができたならば幸いである.

    まとめ

    Appendix: 環境構築

    本書を読み進めるにあたって,ハンズオンのプログラムを実行するための環境を自分のローカルマシンにセットアップしなければならない. ここでは, AWS やコマンドラインの初心者を想定して,本章で必要なソフトウェアやライブラリのインストールなどを簡単に解説する. 以下に簡単な目次を示そう. 既に環境構築が済んでいる場合は適宜読み飛ばしていただき,関係のある箇所のみ目を通せば良い.

    使用する OS は Linux/Mac/Windows のどれを用いても構わない. Windows のユーザーは, Windows Subsytem for Linux (WSL) を使用することを想定している (WSL のインストール).

    また,本書のハンズオンを実行するための Docker イメージ を提供している. これを用いると, AWS CLI/CDK や Python の設定などをスキップできるので, Docker の使用方法を知っている読者には便利だろう.

    AWS アカウントの取得

    本書で提供するハンズオンを実際に自分で試すには,読者自身で AWS のアカウントの作成をする必要がある. 詳しいアカウントの作成の手順は 公式のドキュメンテーション に書かれているので,そちらも参照していただきたい. 以下の手順に従ってアカウントの作成を行う.

    まず,ウェブブラウザから AWS コンソール にアクセスし,右上の Create an AWS Account をクリックする (figure_title で実線で囲った部分).

    サインアップ (1): AWS コンソールにアクセス

    次に,遷移した先のページでメールアドレスとパスワードなどの登録を行う (figure_title).

    サインアップ (2): メールアドレス・パスワードなどの登録.

    続いて,住所や電話番号などを訊かれるので,すべて入力しよう (figure_title).

    サインアップ (3): 住所・電話番号の入力

    次に,クレジットカードの情報の登録を求められる (figure_title). 個人で AWS を利用する場合は,利用料金の請求はクレジットカードを経由して行われる. クレジットカードの登録なしには AWS を使い始めることはできないことに注意.

    サインアップ (4): クレジットカードの登録

    次の画面では,携帯電話の SMS またはボイスメッセージを利用した本人確認が求められる (figure_title). 希望の認証方法を選択し,自分の携帯電話番号を入力しよう.

    サインアップ (5): 携帯電話による本人確認

    無事に本人確認が完了すると,最後にサポートプランの選択を求められる (figure_title). 無料の Basic support を選択しておけば問題ない.

    サインアップ (6): サポートプランの選択

    以上のステップにより,アカウントの作成が完了する (figure_title). 早速ログインをして, AWS コンソールにアクセスできるか確認しておこう.

    サインアップ (7): アカウントの作成が完了した

    AWS のシークレットキーの作成

    AWS シークレットキーとは, AWS CLI や AWS CDK から AWS の API を操作するときに,ユーザー認証を行うための鍵のことである. AWS CLI/CDK を使うには,最初にシークレットキーを発行する必要がある. AWS シークレットキーの詳細は 公式ドキュメンテーション "Understanding and getting your AWS credentials" を参照.

    1. AWS コンソールにログインする.

    2. 画面右上のアカウント名をクリックし,表示されるプルダウンメニューから "My Security Credentials" を選択 (figure_title)

    3. "Access keys for CLI, SDK, & API access" の下にある "Create accesss key" のボタンをクリックする (figure_title)

    4. 表示された Access key ID, Secret access key を記録しておく (画面を閉じると二度と表示されない).

    5. 鍵を忘れてしまった場合などは,同じ手順で再発行が可能である.

    6. 発行したシークレットキーは, ~/.aws/credentials のファイルに書き込むか,環境変数に設定するなどして使う (詳しくは AWS CLI のインストール).

    AWS シークレットキーの発行1

    AWS シークレットキーの発行2

    AWS Educate Starter Account を用いている場合は,次の手順でシークレットキーを確認する.

    • AWS Educate のコンソール画面から, vocareum のコンソールに移動する (figure_title).

    • Account Details をクリックし,続いて AWS CLI: Show をクリックする.

    • aws_access_key_id, aws_secret_access_key, aws_session_token が表示される (figure_title). ここで表示された内容を ~/.aws/credentials にコピーする (AWS CLI のインストール 参照). aws_session_token の箇所も漏らさずコピーすること.

    • 続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

      [default] region = us-east-1 output = json

    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).

    vocareum コンソール

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    sh
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    本書のハンズオンではコマンドラインから AWS CLI のコマンドを実行したり, Python で書かれたプログラムを実行する. コマンドは基本的に UNIX のターミナルを想定して書かれている. Linux や Mac のユーザーは OS に標準搭載されているターミナルを用いれば良い. Windows を利用している読者は, Windows Subsystem for Linux (WSL) を利用することで,仮想の Linux 環境を構築することを推奨する. Cygwin などの Linux 環境をエミュレートするほかのツールでも構わないが,本書のプログラムは WSL でのみ動作確認を行っている.

    WSL とは, Windows の OS 上で Linux の仮想環境を起動するための, Microsoft 社が公式で提供しているソフトウェアである. Ubuntu など希望の Linux distribution が選択でき,基本的にすべての Linux 向けに作られたプログラム・ソフトウェアを使用することができる.

    執筆時点では WSL 2 が最新版として提供されているので,以下では WSL 2 のインストール手順を簡単に説明する. 細かな詳細などは, 公式ドキュメンテーション を参照のこと.

    前提として,使用される OS は Windows 10 (Pro または Home エディション) でなければならない. さらに,使用している Windows 10 のバージョンが WSL に対応するバージョンであるかを確認する. X64 のシステムでは Version 1903, Build 18362 以上でなければならない. バージョンが対応していない場合は、 Windows のアップデートを行う.

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    powersh
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    sh
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    Ubuntu 20.04 を初回に起動すると,初期設定が自動で開始され,数分待つことになる. 初期設定が終わると,ユーザー名・パスワードを設定するようプロンプトが出るので,プロンプトに従い入力する.

    これで WSL2 のインストールが完了した. 早速 WSL2 を起動してみよう. 左下の Windows メニューの検索バーに Ubuntu と入力すると, Ubuntu 20.04 のプログラムが見つかるはずである (figure_title). クリックして起動しよう.

    Ubuntu 20.04 の起動

    すると,ターミナルの黒い画面が立ち上がるだろう (figure_title). ls, top などのコマンドを打ってみて, WSL がきちんと動作していることを確認しよう.

    WSL の起動画面

    オプションとして, Windows Terminal というマイクロソフトから提供されているツールを使うと,より快適に WSL を使用することができる. 興味のある読者はこちらのインストールも推奨する.

    Docker のインストール

    Docker のインストールの方法は OS によって異なる.

    Mac ユーザーは, Docker Desktop をインストールする. インストールの方法は, Docker のウェブサイト から, Mac 版の Docker Desktop をダウンロードし,ダウンロードされたファイルをダブルクリックし, Applications のフォルダにドラッグするだけで良い. 詳細は 公式ドキュメンテーション を参照のこと.

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh\n$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh\n$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    ハンズオンを実行するために必要な, Node.js, Python, AWS CDK などがインストールされた Docker image を用意した. これを使用することで,自分のローカルマシンに諸々をインストールする必要なく,すぐにハンズオンのコードが実行できる.

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    sh
    root@aws-handson:~/programlisting
    root@aws-handson:~/programlisting

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい (プログラムを実行する など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    ライセンス

    本教科書およびハンズオンのソースコードは CC BY-NC-ND 4.0 に従うライセンスで公開しています.

    教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.

    ',1318);function Ia(xa,Ta,Wa,$a,La,Ga){const p=l;return _a(),ka("div",null,[wa,va(p,{readTime:"141",words:"34.3k"}),Pa])}const ln=Ea(Sa,[["render",Ia]]);export{pn as __pageData,ln as default}; diff --git a/assets/development_aws_main.md.587d14dd.lean.js b/assets/development_aws_main.md.587d14dd.lean.js new file mode 100644 index 00000000..3b29f70a --- /dev/null +++ b/assets/development_aws_main.md.587d14dd.lean.js @@ -0,0 +1 @@ +import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o}from"./chunks/earth_from_earth.8c108f53.js";import{_ as e,a as t,b as r,c}from"./chunks/terminal.94539704.js";import{_ as i,a as y,b as d,c as u,d as A,e as C,f as b,g as m,h as F,i as D,j as h}from"./chunks/iac.2263bc12.js";import{_ as s,a}from"./chunks/VPC.e1acca4d.js";import{_ as g,a as B,b as E,c as _,d as k,e as v,f}from"./chunks/ec2_keypair_console.fc89ef69.js";import{_ as q,a as S}from"./chunks/cnn.a8836fd9.js";import{_ as w,a as P,b as I,c as x,d as T,e as W,f as $,g as L,h as G,i as N,j as U,k as R,l as X,m as M,n as H,o as z,p as O}from"./chunks/mnist_prediction.4ba5b405.js";import{_ as j,a as V,b as K,c as Y,d as J,e as Q,f as Z,g as ss}from"./chunks/ecs.73d77e6a.js";import{_ as as,a as ns,b as ps,c as ls,d as os,e as es,f as ts,g as rs,h as cs,i as is,j as ys}from"./chunks/ask_many_output.0bb19110.js";import{_ as ds,a as us,b as As,c as Cs,d as bs,e as ms,f as Fs,g as Ds,h as hs,i as gs,j as Bs,k as Es,l as _s,m as ks,n as vs,o as fs,p as qs,q as Ss,r as ws,s as Ps}from"./chunks/cloud_development.e43e5d4a.js";import{_ as Is,a as xs}from"./chunks/rest_api.602a6e96.js";import{_ as Ts,a as Ws,b as $s,c as Ls,d as Gs}from"./chunks/s3_vs_filesystem.fd65005d.js";import{_ as Ns,a as Us,b as Rs,c as Xs,d as Ms,e as Hs,f as zs,g as Os,h as js,i as Vs,j as Ks,k as Ys,l as Js}from"./chunks/s3_bucket_filelist.89f3f384.js";import{_ as Qs,a as Zs,b as sa,c as aa,d as na,e as pa,f as la,g as oa,h as ea}from"./chunks/bashoutter_2.cd8a2a95.js";import{_ as ta,a as ra,b as ca,c as ia,d as ya,e as da,f as ua,g as Aa,h as Ca,i as ba,j as ma,k as Fa,l as Da,m as ha,n as ga,o as Ba}from"./chunks/venv_shell.dc2530bc.js";import{_ as Ea,o as _a,c as ka,H as va,k as n,a as fa,Q as qa}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const pn=JSON.parse('{"title":"はじめに!","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/main.md","filePath":"development/aws/main.md","lastUpdated":1699051935000}'),Sa={name:"development/aws/main.md"},wa=n("h1",{id:"はじめに",tabindex:"-1"},[fa("はじめに! "),n("a",{class:"header-anchor",href:"#はじめに","aria-label":'Permalink to "はじめに!"'},"​")],-1),Pa=qa("",1318);function Ia(xa,Ta,Wa,$a,La,Ga){const p=l;return _a(),ka("div",null,[wa,va(p,{readTime:"141",words:"34.3k"}),Pa])}const ln=Ea(Sa,[["render",Ia]]);export{pn as __pageData,ln as default}; diff --git a/assets/development_aws_main.md.58c079df.js b/assets/development_aws_main.md.58c079df.js deleted file mode 100644 index 3a778742..00000000 --- a/assets/development_aws_main.md.58c079df.js +++ /dev/null @@ -1,1911 +0,0 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o}from"./chunks/earth_from_earth.8c108f53.js";import{_ as e,a as t,b as r,c}from"./chunks/terminal.94539704.js";import{_ as i,a as y,b as d,c as u,d as b,e as m,f as A,g as h,h as B,i as g,j as _}from"./chunks/iac.2263bc12.js";import{_ as s,a}from"./chunks/VPC.e1acca4d.js";import{_ as f,a as k,b as v,c as q,d as D,e as C,f as S}from"./chunks/ec2_keypair_console.fc89ef69.js";import{_ as w,a as P}from"./chunks/cnn.a8836fd9.js";import{_ as E,a as I,b as z,c as x,d as T,e as W,f as $,g as L,h as G,i as N,j as U,k as R,l as X,m as M,n as H,o as F,p as O}from"./chunks/mnist_prediction.4ba5b405.js";import{_ as j,a as V,b as K,c as Y,d as J,e as Q,f as Z,g as ss}from"./chunks/ecs.73d77e6a.js";import{_ as as,a as ns,b as ps,c as ls,d as os,e as es,f as ts,g as rs,h as cs,i as is,j as ys}from"./chunks/ask_many_output.0bb19110.js";import{_ as ds,a as us,b as bs,c as ms,d as As,e as hs,f as Bs,g as gs,h as _s,i as fs,j as ks,k as vs,l as qs,m as Ds,n as Cs,o as Ss,p as ws,q as Ps,r as Es,s as Is}from"./chunks/cloud_development.e43e5d4a.js";import{_ as zs,a as xs}from"./chunks/rest_api.602a6e96.js";import{_ as Ts,a as Ws,b as $s,c as Ls,d as Gs}from"./chunks/s3_vs_filesystem.fd65005d.js";import{_ as Ns,a as Us,b as Rs,c as Xs,d as Ms,e as Hs,f as Fs,g as Os,h as js,i as Vs,j as Ks,k as Ys,l as Js}from"./chunks/s3_bucket_filelist.89f3f384.js";import{_ as Qs,a as Zs,b as sa,c as aa,d as na,e as pa,f as la,g as oa,h as ea}from"./chunks/bashoutter_2.cd8a2a95.js";import{_ as ta,a as ra,b as ca,c as ia,d as ya,e as da,f as ua,g as ba,h as ma,i as Aa,j as ha,k as Ba,l as ga,m as _a,n as fa,o as ka}from"./chunks/venv_shell.dc2530bc.js";import{_ as va,o as qa,c as Da,H as Ca,k as n,a as Sa,Q as wa}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const pn=JSON.parse('{"title":"はじめに!","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/main.md","filePath":"development/aws/main.md","lastUpdated":1695377563000}'),Pa={name:"development/aws/main.md"},Ea=n("h1",{id:"はじめに",tabindex:"-1"},[Sa("はじめに! "),n("a",{class:"header-anchor",href:"#はじめに","aria-label":'Permalink to "はじめに!"'},"​")],-1),Ia=wa('

    本書の目的・内容

    本書は,東京大学計数工学科で 2021 年度 S1/S2 タームに開講されている"システム情報工学特論"の講義資料として作成された.

    本書の目的は,クラウドの初心者を対象とし,クラウドの基礎的な知識・概念を解説する. また, Amazon Web Services (以下, AWS) の提供するクラウド環境を実例として,具体的なクラウドの利用方法をハンズオンを通して学ぶ.

    とくに,科学・エンジニアリングの学生を対象として,研究などの目的でクラウドを利用するための実践的な手順を紹介する. 知識・理論の説明は最小限に留め,実践を行う中で必要な概念の解説を行う予定である. 読者が今後,研究などでクラウドを利用する際の,足がかりとなれば本書の目的は十分達成されたことになる.

    本書は以下のような三部構成になっている.

    本書の構成
    テーマハンズオン

    第一部 (1章-4章)

    クラウドの基礎

    • AWSに自分のサーバーを立ち上げる

    第二部 (5章-9章)

    クラウドを活用した機械学習

    • AWS と Jupyter を使って始めるディープラーニング

    • スケーラブルな自動質問回答ボットを作る

    • 並列化されたハイパーパラメータサーチの実装

    第三部 (10章-13章)

    サーバーレスアーキテクチャ入門

    • Lambda, DynamoDB, S3 の演習

    • 俳句を投稿する SNS "Bashoutter" を作る

    第一部は,クラウドの基礎となる概念・知識を解説する. セキュリティやネットワークなど,クラウドを利用する上で最低限おさえなければいけないポイントを説明する. ハンズオンでは,はじめての仮想サーバーを AWS に立ち上げる演習を行う.

    第二部では,クラウド上で科学計算 (とくに機械学習) を走らせるための入門となる知識・技術を解説する. あわせて, Docker とよばれる仮想計算環境の使用方法を紹介する. 一つ目のハンズオンでは, AWS のクラウドで Jupyter Notebook を起動し簡単な機械学習の計算を走らせる課題を実践する. 二つ目のハンズオンでは,深層学習を用いた自然言語処理により,質問に自動で回答を生成するボットを作成する. 最後に,複数台の GPU インスタンスからなるクラスターを起動し,並列に深層学習のハイパーパラメータサーチを行う方法を紹介する.

    第三部では,サーバーレスアーキテクチャとよばれる最新のクラウドのアーキテクチャを紹介する. これは,サーバーの処理能力を負荷に応じてより柔軟に拡大・縮小するための概念であり,それ以前 (Serverful としばしばよばれる) と質的に異なる設計思想をクラウドに導入するものである. ハンズオンでは,サーバーレスクラウドの主要なコンポーネントである Lambda, DynamoDB, S3 の演習を提供する. さらに,サーバーレスの技術を使用して簡単な SNS をクラウド上に作成する.

    これらの豊富なハンズオンにより, AWS 上にクラウドシステムを開発するための知識と技術が身につくはずである. いずれのハンズオンも,実用性を重視したものになっており,これらをベースにカスタマイズを施すことで様々な応用が可能である.

    本書のフィロソフィー

    本書のフィロソフィーを一言で表すなら, "ロケットで宇宙まで飛んでいって一度地球を眺めてみよう!" である.

    どういうことか?

    ここでいう"地球"とは,クラウドコンピューティングの全体像のことである. 言うまでもなく,クラウドという技術は非常に広範かつ複雑な概念で,幾多の情報技術・ハードウェア・アルゴリズムが精緻に組み合わさってできた総体である. そして,今日では科学研究から日常のインフラ設備に至るまで,我々の社会の多くの部分がクラウド技術によって支えられている.

    ここでいう"ロケット"とはこの講義のことである. この講義では,ロケットに乗って宇宙まで飛び立ち,地球(クラウド)の全体を自身の目で眺めてもらう. その際,ロケットの成り立ちや仕組み (背後にある要素技術やプログラムのソースコード) を深くは問わない. 将来,自分が研究などの目的でクラウドを利用することになった際に,改めて学んでもらえば良い. 本書の目的はむしろ,クラウドの最先端に実際に触れ,そこからどんな景色が見えるか(どんな応用が可能か)を実感してもらうことである.

    そのような理由で,本書はクラウドの基礎から応用まで幅広いテーマを取り扱う. 第一部はクラウドの基礎から始め,第二部では一気にレベルアップし機械学習(深層学習)をクラウドで実行する手法を解説する. さらに第三部では,サーバーレス・アーキテクチャというここ数年のうちに確立した全く新しいクラウドの設計について解説する. それぞれで本一冊分以上の内容に相当するものであるが,本書はあえてこれらを一冊にまとめ連続的に俯瞰するという野心的な意図をもって執筆された.

    決して楽な搭乗体験ではないかもしれないが,このロケットにしがみついてきてもらえれば,とてもエキサイティングな景色が見られることを約束したい.

    宇宙からみた地球 (Image from NASA https://www.nasa.gov/image-feature/planet-of-clouds)

    AWS アカウント

    本書では,ハンズオン形式で AWS のクラウドを実際に動かす演習を提供する. 自分でハンズオンを実行してみたい読者は,各自で AWS のアカウントの作成をしていただく. AWS のアカウントの作成の仕方は巻末付録 (AWS アカウントの取得) に簡単に記載したので,必要に応じて参照していただきたい.

    AWS にはいくつかの機能に対して無料利用枠が設定されており,いくつかのハンズオンは無料の範囲内で実行できる. 一方,ほかのハンズオン (とくに機械学習を扱うもの) では数ドル程度のコストが発生する. ハンズオンごとに発生するおおよそのコストについて記述があるので,注意をしながらハンズオンに取り組んでいただきたい.

    また,大学などの教育機関における講義で AWS を使用する際は, AWS Educate というプログラムを利用することも可能である. これは,講義の担当者が申請を行うことで,受講する学生に対し AWS クレジットが提供されるというプログラムである. AWS Educate を利用することで金銭的な負担なしに AWS を体験することができる. また,講義を経由せず個人でも AWS Educate に参加することも可能である. AWS Educate からは様々な学習教材が提供されているので,ぜひ活用してもらいたい.

    環境構築

    本書では, AWS 上にクラウドアプリケーションを展開するハンズオンを実施する. そこで紹介するプログラムを実行するためには,以下の計算機環境が必要である. インストールの方法については,巻末付録 (Appendix: 環境構築) に記してある. 必要に応じて参照し,環境構築を各自実施していただきたい.

    • UNIX 系コンソール: ハンズオンで紹介するコマンドを実行したり, SSH でサーバーにアクセスするため, UNIX 系のコンソール環境が必要である. Mac または Linux のユーザーは, OS に標準搭載のコンソール(ターミナルとも呼ばれる)を使用すればよい. Windows のユーザーは, Windows Subsystem for Linux (WSL) を使い, Linux の仮想環境のインストールを推奨する (WSL のインストール 参照).

    • Docker: 本書では Docker とよばれる仮想計算環境の利用方法を解説する. インストール手順については Docker のインストール を参照のこと.

    • Python: Version 3.6 以上をインストールする. とくに,ハンズオンでは venv モジュールを使用する. venv の使い方は Python クイックガイド 参照のこと.

    • Node.js: version 12.0 以上 をインストールする.

    • AWS CLI: Version 2 をインストールする. インストール手順については AWS CLI のインストール 参照のこと.

    • AWS CDK: Version 1.100 以上をインストールする. Version 2 以降には未対応である. インストール手順については AWS CDK のインストール 参照のこと.

    • AWS 認証鍵の設定: AWS API をコマンドラインから呼ぶには,認証鍵 (secret key) が設定されている必要がある. 認証鍵の設定については AWS CLI のインストール 参照のこと.

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は ハンズオン実行用の Docker image の使い方 に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    • Python の基本的な理解: 本書では Python を使ってプログラムの作成を行う. 使用するライブラリは十分抽象化されており,関数の名前を見ただけで意味が明瞭なものがほとんどであるので, Python に詳しくなくても心配する必要はない.

    • Linux コマンドラインの基礎的な理解: クラウドを利用する際,クラウド上に立ち上がるサーバーは基本的に Linux である. Linux のコマンドラインについて知識があると,トラブルシュートなどが容易になる. 筆者のおすすめの参考書は The Linux Command Line by William Shotts である. ウェブで無料で読むことができるので,読んだことのない人はぜひ一読を.

    講義に関連する資料

    ハンズオンで使うプログラムや教科書のソースコードは以下のウェブページで公開している.

    https://github.com/tomomano/learn-aws-by-coding

    本書で使用するノーテーションなど

    • コードやシェルのコマンドは monospace letter で記述する.

    • シェルに入力するコマンドは,それがシェルコマンドであると明示する目的で,先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力には $ はついていない点に留意する.

    また,以下のような形式で注意やチップスを提供する.

    追加のコメントなどを記す.

    発展的な議論やアイディアなどを紹介する.

    陥りやすいミスなどの注意事項を述べる.

    絶対に犯してはならないミスを指摘する.

    クラウド概論

    クラウドとは?

    Cloud

    クラウドとはなにか? クラウドという言葉は,それ自身がとても広い意味をもつので,厳密な定義付けを行うことは難しい.

    学術的な意味でのクラウドの定義づけをするとしたら,NIST(米国・国立標準技術研究所) による The NIST Definition of Cloud Computing が引用されることが多い. ここに記載されたクラウドの定義・モデルを図示したのが figure_title である.

    The NIST Definition of Cloud Computing

    これによると,クラウドとは以下の要件が満たされたハードウェア/ソフトウェアの総体のことをいう.

    • On-demand self-service 利用者のリクエストに応じて計算資源が自動的に割り当てられる.

    • Broad network access 利用者はネットワークを通じてクラウドにアクセスできる.

    • Resource pooling クラウドプロバイダーは,所有する計算資源を分割することで複数の利用者に計算資源を割り当てる.

    • Rapid elasticity 利用者のリクエストに応じて,迅速に計算資源の拡大あるいは縮小を行うことができる.

    • Measured service 計算資源の利用量を計測・監視することができる.

    …と,いわれても抽象的でよくわからないかもしれない.もう少し具体的な話をする.

    個人が所有する計算機で, CPU をアップグレードしようと思ったら,物理的に筐体を開け,CPU ソケットを露出させ,新しい CPU に交換する必要があるだろう. あるいは,ストレージがいっぱいになってしまったら,古いディスクを抜き取り,新しいディスクを挿入する必要がある. 計算機の場所を移動させたときには,新しい部屋の LAN ケーブルを差し込まないとネットワークには接続できない.

    クラウドでは,これらの操作がプログラムからのコマンドによって実行できる. CPU が 1000 個欲しいと思ったならば,そのようにクラウドプロバイダーにリクエストを送れば良い. すると,数分もしないうちに 1000 CPU の計算資源が割り当てられる. ストレージを 1TB から 10TB に拡張しようと思ったならば,そのようにコマンドを送ればよい (これは,Google Drive や Dropbox などのサービスなどで馴染みのある人も多いだろう). 計算資源を使い終わったら,そのことをプロバイダーに伝えれば,割り当て分はすぐさま削除される. クラウドプロバイダーは,使った計算資源の量を正確にモニタリングしており,その量をもとに利用料金の計算が行われる.

    このように,クラウドの本質は物理的なハードウェアの仮想化・抽象化であり,利用者はコマンドを通じて,まるでソフトウェアの一部かのように,物理的なハードウェアの管理・運用を行うことができる. もちろん,背後では,データセンターに置かれた膨大な数の計算機が大量の電力を消費しながら稼働している. クラウドプロバイダーはデータセンターの計算資源を上手にやりくりし,ソフトウェアとしてのインターフェースをユーザーに提供することで,このような仮想化・抽象化を達成しているわけである. クラウドプロバイダーの視点からすると,大勢のユーザーに計算機を貸し出し,データセンターの稼働率を常時 100%に近づけることで,利益率の最大化を図っているのである.

    著者の言葉で,クラウドの重要な特性を定義するならば,以下のようになる.

    クラウドとは計算機ハードウェアの抽象化である.つまり,物理的なハードウェアをソフトウェアの一部かのように自在に操作・拡大・接続することを可能にする技術である.

    先述の The NIST Definition of Cloud Computing に戻ると,クラウドプロバイダーによるクラウドサービスの形態としては,次の三つが定義されている (figure_title).

    • Software as a Service (SaaS): クラウド上で実行されるアプリケーションをサービスとして利用者に提供する形態. 例として, Google Drive や Slack などが挙げられる. 利用者は,背後にあるクラウドのインフラ (ネットワークやサーバーなど) には直接触れず,アプリケーションとして提供されているクラウドサービスを享受する.

    • Platform as a Service (PaaS): 顧客の作成したアプリケーション (多くの場合データベースと API リクエスト処理を行うサーバーのコードから構成される) をデプロイする環境をサービスとして利用者に提供する形態. PaaS では利用者はクラウドのインフラに直接触れることはなく,計算負荷が増減した際のサーバーのスケーリングはクラウドプロバイダーによってなされる. 例としては, Google App Engine や Heroku などがある.

    • Infrastructure as a Service (IaaS): クラウド上の計算インフラストラクチャーを従量課金制で利用者に提供する形態. 利用者は必要なネットワーク・サーバー・ストレージをプロバイダーから借り受け,そこに自身のアプリケーションを展開し運用する. IaaS の例としては AWS EC2 などが挙げられる.

    本書が扱うのは,主に IaaS におけるクラウド開発である. すなわち,開発者がクラウドのインフラを直接操作し,所望のネットワーク・サーバー・ストレージなどを一から構成し,そこにアプリケーションを展開するというクラウド開発である. この意味において,クラウドの開発とはクラウドインフラストラクチャーを定義・展開するプログラムを構築するステップインフラ上で実際に走るアプリケーションを作成するステップの二つに分けることができる. この二つは,プログラマーの技術としてはある程度分業を行うことが可能であるが,最も効率化・最適化されたクラウドシステムを構築するためには両方の理解が必須である. 本書では,前者 (クラウドインフラの記述) に重きを置きつつ,アプリケーションレイヤーの話題も取り扱う. PaaS とは,開発者はアプリケーションレイヤーの開発に注力し,クラウドインフラの部分はクラウドプロバイダーに依存するという概念である. PaaS は,クラウドインフラの開発が不要になることで開発の時間が短縮されるが,細かなインフラの挙動はコントロールできないという限界がある. 本書では PaaS についてはとくに取り扱わない.

    SaaS は本書の文脈では開発による"成果物"と捉えられるだろう. すなわち, IaaS を構成するプログラムを作成し展開することによって,一般の人が利用できるようなウェブ上の計算サービスやデータベースを提供することが開発の最終ゴールである. 本書のハンズオンではその実例として,シンプルな SNS の作成 (Hands-on #6: Bashoutter) などの演習を提供する.

    なお,最近では Function as a Service (FaaS) やサーバーレスコンピューティングなども新たなクラウドのカテゴリとして認知されている. これらの概念については Hands-on #5: サーバーレス入門 などの章で詳しく触れていく. 本書を読み進める中で明らかになるように,クラウドの技術は日進月歩である. 本書では実用的・教育的な観点から,従来的なクラウドの設計概念に触れたあと,サーバーレスなどの最新の技術も網羅するので,楽しみにしながら読み進めていただきたい.

    最後に,The NIST Definition of Cloud Computing によると,クラウドの運用形態について次のような定義がなされている (figure_title). 特定の組織・団体・企業の内部のみで使用されるクラウドを,プライベートクラウド (private cloud) とよぶ. 例えば,大学や研究機関では,その機関の構成員向けの大規模計算機サーバーが運用されていることが多い. プライベートクラウドは,組織の構成員ならば無料もしくは極めて割安のコストで計算を実行できる. しかし,使用できる計算資源の上限は限られる場合が多く,拡張時の柔軟性に欠ける場合もある.

    一方,商用のサービスとして一般の顧客に向けたクラウドのことを,パブリッククラウド (public cloud) とよぶ. 有名なパブリッククラウドプラットフォームの例を挙げると, Google 社が提供する Google Cloud Platform (GCP), Microsoft 社が提供する Azure, Amazon 社が提供する Amazon Web Services (AWS) などがある. パブリッククラウドを利用する場合は,プロバイダーの設定した利用料金を支払うことになる. その分,巨大なデータセンターを運用する企業の計算資源にアクセスすることができるので,計算のキャパシティは無尽蔵にあるといって過言でない.

    第三のクラウドの運用形態として,コミュニティクラウド (community cloud) が挙げられる. これは,例えば政府の省庁・機関など目的・役割を共有する団体・組織が共有して運用するクラウドを指す. 最後に,ハイブリッドクラウド (hybrid cloud) という形態もあり,これはプライベート・パブリック・コミュニティクラウドの二つ以上の組み合わせによって構成されるクラウドのことである. データ保護の観点から,いくつかの機密データやプライバシーに関わる情報はプライベートクラウドに保持し,残りのシステムをパブリッククラウドに依存する,などの形態が想定される.

    本書で説明するのは,基本的にパブリッククラウドを使ったクラウド開発である. 特に,Amazon Web Services (AWS) を使用して,具体的な技術と概念を学んでいく. 一方で,サーバーのスケーリングや仮想計算環境などのテクニックはすべてのクラウドに共通な概念であるので,クラウドのプラットフォームが変わろうと一般に通用する知識も同時に身につくはずだ.

    なぜクラウドを使うのか?

    上述のように,クラウドとはプログラムを通じて自由に計算資源を操作することのできる計算環境である. ここでは,リアルなローカル計算環境と比べて,なぜクラウドを使うと良いことがあるのかについて述べたい.

    1. 自由にサーバーのサイズをスケールできる

      なにか新しいプロジェクトを始めるとき,あらかじめ必要なサーバーのスペックを知るのは難しい. いきなり大きなサーバーを買うのはリスクが高い. 一方で,小さすぎるサーバーでは,後のアップグレードが面倒である. クラウドを利用すれば,プロジェクトを進めながら,必要な分だけの計算資源を確保することができる. 2. 自分でサーバーをメンテナンスする必要がない

      悲しいことに,コンピュータとは古くなるものである.最近の技術の進歩の速度からすると,5 年も経てば,もはや当時の最新コンピュータも化石と同じである. 5 年ごとにサーバーを入れ替えるのは相当な手間である. またサーバーの停電や故障など不意の障害への対応も必要である. クラウドでは,そのようなインフラの整備やメンテナンスはプロバイダーが自動でやってくれるので,ユーザーが心配する必要がない. 3. 初期コスト 0

      自前の計算環境とクラウドの,経済的なコストのイメージを示したのが figure_title である. クラウドを利用する場合の初期コストは基本的に 0 である. その後,使った利用量に応じてコストが増大していく. 一方,自前の計算環境では,大きな初期コストが生じる. その分,初期投資後のコストの増加は,電気利用料やサーバー維持費などに留まるため,クラウドを利用した場合よりも傾きは小さくなる. 自前の計算機では,ある一定期間後,サーバーのアップグレードなどによる支出が生じることがある. 一方,クラウドを利用する場合は,そのような非連続なコストの増大は基本的に生じない. クラウドのコストのカーブが,自前計算環境のコストのカーブの下にある範囲においては,クラウドを使うことは経済的なコスト削減につながる.

      クラウドと自前計算機環境の経済的コストの比較

    とくに,**1.**の点は研究の場面では重要であると筆者は感じる. 研究をやっていて,四六時中計算を走らせ続けるという場合は少ない. むしろ,新しいアルゴリズムが完成したとき・新しいデータが届いたとき,集中的・突発的に計算タスクが増大することが多いだろう. そういったときに,フレキシブルに計算力を増強させることができるのは,クラウドを使う大きなメリットである.

    ここまでクラウドを使うメリットを述べたが,逆に,デメリットというのも当然存在する.

    1. クラウドは賢く使わないといけない

      figure_title で示したコストのカーブにあるとおり,使い方によっては自前の計算環境のほうがコスト的に有利な場面は存在しうる. クラウドを利用する際は,使い終わった計算資源はすぐに削除するなど,利用者が賢く管理を行う必要があり,これを怠ると思いもしない額の請求が届く可能性がある. 2. セキュリティ

      クラウドは,インターネットを通じて世界のどこからでもアクセスできる状態にあり,セキュリティ管理を怠ると簡単にハッキングの対象となりうる. ハッキングを受けると,情報流出だけでなく,経済的な損失を被る可能性がある. 3. ラーニングカーブ

      上記のように,コスト・セキュリティなど,クラウドを利用する際に留意しなければならない点は多い. 賢くクラウドを使うには,十分なクラウドの理解が必要であり,そのラーニングカーブを乗り越える必要がある.

    Mac/Linux などでコマンドを入力するときに使用する,あの黒い画面のことを Terminal とよんだりする. この言葉の語源をご存知だろうか?

    Terminal

    この言葉の語源は,コンピュータが誕生して間もない頃の時代に遡る. その頃のコンピュータというと,何千何万のという数の真空管が接続された,会議室一個分くらいのサイズのマシンであった. そのような高価でメンテが大変な機材であるから,当然みんなでシェアして使うことが前提となる. ユーザーがコンピュータにアクセスするため,マシンからは何本かのケーブルが伸び,それぞれにキーボードとスクリーンが接続されていた… これを Terminal とよんでいたのである. 人々は,代わる代わる Terminal の前に座って,計算機との対話を行っていた.

    時代は流れ,Windows や Mac などのいわゆるパーソナルコンピュータの出現により,コンピュータはみんなで共有するものではなく,個人が所有するものになった.

    最近のクラウドの台頭は,みんなで大きなコンピュータをシェアするという,最初のコンピュータの使われ方に原点回帰していると捉えることもできる. 一方で,スマートフォンやウェアラブルなどのエッジデバイスの普及も盛んであり,個人が複数の"小さな"コンピュータを所有する,という流れも同時に進行しているのである.

    AWS 入門

    AWS とは?

    本書では,クラウドの実践を行うプラットフォームとして, AWS を用いる. 実践にあたって,最低限必要な AWS の知識を本章では解説しよう.

    AWS (Amazon Web Services) は Amazon 社が提供する総合的なクラウドプラットフォームである. AWS は Amazon 社が持つ膨大な計算リソースを貸し出すクラウドサービスとして,2006 年に誕生した. 2021 年では,クラウドプロバイダーとして最大のマーケットシェア (約 32%) を保持している (参照). Netflix や Slack をはじめとした多くのウェブ関連のサービスで,一部または全てのサーバーリソースが AWS から提供されているとのことである. よって,知らないうちに AWS の恩恵にあずかっている人も少なくないはずだ.

    最大のシェアをもつだけに,機能・サービスの幅広さはほかのクラウドプラットフォームと比べ抜きんでている. また,利用者数が多いことを反映して,公式あるいはサードパーティによる技術紹介記事が数多くウェブ上に存在しているだけでなく,ライブラリのユーザーコミュニティも大きく問題解決が捗るのも魅力の一つだ. 初期のころウェブビジネスを行う企業がユーザーの大半を占めていたが,最近は大学などでの科学研究用途としても頻繁に用いられるようになってきている.

    AWS の機能・サービス

    figure_title は,執筆時点において AWS で提供されている主要な機能・サービスの一覧である.

    AWSで提供されている主要なサービス一覧

    計算,ストレージ,データベース,ネットワーク,セキュリティなど,クラウドの構築に必要な様々な要素が独立したコンポーネントとして提供されている. 基本的に,これらを組み合わせることで一つのクラウドシステムができあがる.

    また,機械学習・音声認識・AR/VR など,特定のアプリケーションにパッケージ済みのサービスも提供されている. これらを合計すると全部で 170 個以上のサービスが提供されているとのことである (参照).

    AWS の初心者が陥りがちなのは,大量のサービスの数に圧倒され,どこから手をつけたらよいのかわからなくなる,という状況である. たくさんのサービスの中から,どのサービスをどの順番で学んでいったらいいのか,その道筋すら明らかでなく,大きな参入障壁となっていることは間違いない. だが実のところ, AWS の基本的な構成要素はそのうちの数個のみに限られる. 基本要素となる機能の使い方を知れば, AWS のおおよそのリソースを使いこなすことが可能になる. ほかの機能の多くは,基本の要素を組み合わせて特定のアプリケーションに特化したパッケージとして AWS が用意したものである. そのポイントを認知することが, AWS の学習の最初のステップである.

    ここでは, AWS 上でクラウドシステムを構築するときの基本となる構成要素を列挙する. これらは後のハンズオンで実際にプログラムを書きながら体験する. 現時点では,名前だけでも頭の片隅に記憶してもらえればよい.

    計算

    S3 EC2 (Elastic Compute Cloud) 様々なスペックの仮想マシンを作成し,計算を実行することができる. クラウドの最も基本となる構成要素である. Hands-on #1: 初めての EC2 インスタンスを起動する, Hands-on #2: AWS でディープラーニングを実践, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で詳しく触れる.

    S3 Lambda Function as a Service (FaaS) とよばれる,小さな計算をサーバーなしで実行するためのサービス. サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    ストレージ

    S3 EBS (Elastic Block Store) EC2 に付与することのできる仮想データドライブ. いわゆる"普通の"(一般的な OS で使われている)ファイルシステムを思い浮かべてくれたらよい.

    S3 S3 (Simple Storage Service) Object Storage とよばれる,API を使ってデータの読み書きを行う,いうなれば”クラウド・ネイティブ”なデータの格納システムである. サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    データベース

    S3 DynamoDB NoSQL 型のデータベースサービス (知っている人は mongoDB などを思い浮かべたらよい). サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    ネットワーク

    S3 VPC(Virtual Private Cloud) AWS 上に仮想ネットワーク環境を作成し,仮想サーバー間の接続を定義したり,外部からのアクセスなどを管理する. EC2 は VPC の内部に配置されなければならない.

    API Gateway S3 API のエンドポイントとバックエンドのサービス (Lambda など) を接続する際に用いる,リバースプロキシとしての役割を担う. Hands-on #6: Bashoutter で詳しく解説する.

    Region と Availability Zone

    AWS を使用する際に知っておかなければならない重要な概念として, リージョン (Region)Availability Zone (AZ) がある (figure_title). 以下ではこの概念について簡単に記述する.

    AWSにおける Region と Availability Zones

    リージョン (Region) とは,おおまかに言うとデータセンターの所在地のことである. 執筆時点において, AWS は世界の 25 の国と地域でデータセンターを所有している. figure_title は執筆時点で利用できるリージョンの世界地図を示している. 日本では東京と大阪にデータセンターがある. 各リージョンには固有の ID がついており,例えば東京は ap-northeast-1, 米国オハイオ州は us-east-2,などと定義されている.

    Regions in AWS(出典: https://aws.amazon.com/about-aws/global-infrastructure/)

    AWS コンソールにログインすると,画面右上のメニューバーでリージョンを選択することができる(figure_title, 赤丸で囲った箇所). EC2, S3 などの AWS のリソースは,リージョンごとに完全に独立である. したがって,リソースを新たにデプロイする際,あるいはデプロイ済みのリソースを閲覧する際は,コンソールのリージョンが正しく設定されているか,確認する必要がある. ウェブビジネスを展開する場合などは,世界の各地にクラウドを展開する必要があるが,個人的な研究用途として用いる場合は,最寄りのリージョン (i.e. 東京) を使えば基本的に問題ない.

    AWSコンソールでリージョンを選択

    Avaialibity Zone (AZ) とは,リージョン内で地理的に隔離されたデータセンターのことである. それぞれのリージョンは 2 個以上の AZ を有しており,もし一つの AZ で火災や停電などが起きた場合でも,ほかの AZ がその障害をカバーすることができる. また, AZ 間は高速な AWS 専用ネットワーク回線で結ばれているため, AZ 間のデータ転送は極めて早い. AZ は,ビジネスなどでサーバーダウンが許容されない場合などに注意すべき概念であり,個人的な用途で使う限りにおいてはあまり深く考慮する必要はない.言葉の意味だけ知っておけば十分である.

    AWS を使用する際,どこのリージョンを指定するのがよいのだろうか? インターネットの接続速度の観点からは,地理的に一番近いリージョンを使用するのが一般的によいだろう. 一方, EC2 の利用料などはリージョンごとに価格設定が若干 (10-20%程度) 異なる. したがって,自分が最も頻繁に利用するサービスの価格が最も安く設定されているリージョンを選択する,というのも重要な視点である. また,いくつかのサービスは,特定のリージョンで利用できない場合もある. これらのポイントから総合的に判断して使用するリージョンを決めると良い.

    AWS Educate を利用している読者へ

    執筆時点において,AWS Educate による Starter Account を使用している場合は us-east-1 region のみ利用できる (参照).

    AWS でのクラウド開発

    AWS のクラウドの全体像がわかってきたところで,次のトピックとして,どのようにして AWS 上にクラウドの開発を行い,展開していくかについての概略を解説しよう.

    AWS のリソースを追加・編集・削除するなどの操作を実行するには,コンソールを用いる方法と,API を用いる方法の,二つの経路がある.

    コンソール画面からリソースを操作する

    AWS のアカウントにログインすると,まず最初に表示されるのがAWS コンソールである (figure_title).

    AWSマネージメントコンソール画面

    コンソールを使うことで, EC2 のインスタンスを立ち上げたり,S3 のデータを追加・削除したり,ログを閲覧したりなど,AWS 上のあらゆるリソースの操作を GUI (Graphical User Interface) を通して実行することができる. 初めて触る機能をポチポチと試したり,デバッグを行うときなどにとても便利である

    コンソールはさらっと機能を試したり,開発中のクラウドのデバッグをするときには便利なのであるが,実際にクラウドの開発をする場面でこれを直接いじることはあまりない. むしろ,次に紹介する API を使用して,プログラムとしてクラウドのリソースを記述することで開発を行うのが一般的である. そのような理由で,本書では AWS コンソールを使った AWS の使い方はあまり触れない. AWS のドキュメンテーションには,たくさんの チュートリアル が用意されており,コンソール画面から様々な操作を行う方法が記述されているので,興味がある読者はそちらを参照されたい.

    API からリソースを操作する

    API (Application Programming Interface) を使うことで,コマンドを AWS に送信し,クラウドのリソースの操作をすることができる. API とは,端的に言えば AWS が公開しているコマンドの一覧であり,GET, POST, DELETE などの REST API から構成されている (REST API については REST API で簡単に解説する). が,直接 REST API を入力するのは面倒であるので,その手間を解消するための様々なツールが提供されている.

    例えば, AWS CLI は, UNIX コンソールから AWS API を実行するための CLI (Command Line Interface) である. CLI に加えて,いろいろなプログラミング言語での SDK (Software Development Kit) が提供されている.以下に一例を挙げる.

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    python
    import boto3
    -
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    -
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン (Hands-on #1: 初めての EC2 インスタンスを起動する) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    python
    import boto3
    -
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    import boto3
    -
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    AWS CLI のインストールについては, AWS CLI のインストール を参照.

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは AWS CLI のインストール を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://\${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://\${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    sh
    $ aws s3 ls
    -
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    -
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    sh
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://\${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://\${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    sh
    $ aws s3 ls "s3://\${bucketName}" --human-readable
    -
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://\${bucketName}" --human-readable
    -
    -2020-06-07 23:54:19   13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    sh
    $ aws s3 rb "s3://\${bucketName}" --force
    $ aws s3 rb "s3://\${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    AWS 上のあらゆるリソースには, Amazon Resource Name (ARN) という固有の ID が付与されている. ARN は arn:aws:s3:::my_bucket/ のようなフォーマットで記述され,ARN を使用することで,特定の AWS リソース (S3 のバケットや EC2 のインスタンス) を一意的に参照することができる.

    S3 バケットや EC2 インスタンスなどには ARN に加えて,人間が読みやすい名前を定義することも可能である. この場合は,ARN または名前のどちらを用いても同じリソースを参照することが可能である.

    CloudFormation と AWS CDK

    CloudFormation による Infrastructure as Code (IaC)

    前節で述べたように,AWS API を使うことでクラウドのあらゆるリソースの作成・管理が可能である. よって,原理上は, API のコマンドを組み合わせていくことで,自分の作りたいクラウドを設計することができる.

    しかし,ここで実用上考慮しなければならない点が一つある. AWS API には大きく分けて,リソースを操作するコマンドと,タスクを実行するコマンドがあることである (figure_title).

    AWS APIはリソースを操作するコマンドとタスクを実行するコマンドに大きく分けられる.リソースを記述・管理するのに使われるのが, CloudFormation と CDK である.

    リソースを操作するとは,EC2 のインスタンスを起動したり,S3 のバケットを作成したり,データベースに新たなテーブルを追加する,などの静的なリソースを準備する 操作を指す. "ハコ"を作る操作とよんでも良いだろう. このようなコマンドは,クラウドのデプロイ時にのみ,一度だけ実行されればよい

    タスクを実行するコマンド とは, EC2 のインスタンスにジョブを投入したり, S3 のバケットにデータを読み書きするなどの操作を指す. これは, EC2 や S3 などのリソース ("ハコ") を前提として,その内部で実行されるべき計算を記述するものである. 前者に比べてこちらは動的な操作を担当する,と捉えることもできる.

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    json
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\\n",
    -                     "yum update -y aws-cfn-bootstrap\\n",
    -
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\\n",
    -
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\\n",
    -                     "yum update -y aws-cfn-bootstrap\\n",
    -
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\\n",
    -
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    python
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    -
    -class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    -
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    -
    -class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    -
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

    • AWS CDK Examples: CDK を使ったプロジェクトの例が多数紹介されている. ここにある例をテンプレートに自分のアプリケーションの開発を進めるとよい.

    Hands-on #1: 初めての EC2 インスタンスを起動する

    ハンズオンの第一回では, CDK を使って EC2 のインスタンス(仮想サーバー)を作成し,SSH でサーバーにログインする,という演習を行う. このハンズオンを終えれば,あなたは自分だけのサーバーを AWS 上に立ち上げ,自由に計算を走らせることができるようになるのである!

    準備

    ハンズオンのソースコードは GitHub の handson/ec2-get-started に置いてある.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行することができる.

    まずは,ハンズオンを実行するための環境を整える. これらの環境整備は,後のハンズオンでも前提となるものなので確実にミスなく行っていただきたい.

    • AWS Account: ハンズオンを実行するには個人の AWS アカウントが必要である. AWS アカウントの取得については AWS アカウントの取得 を参照のこと.
    • Python と Node.js: 本ハンズオンを実行するには,Python (3.6 以上),Node.js (12.0 以上) がインストールされていなければならない.
    • AWS CLI: AWS CLI のインストールについては, AWS CLI のインストール を参照. ここに記載されている認証鍵の設定も済ませておくこと.
    • AWS CDK: AWS CDK のインストールについては, AWS CDK のインストール を参照.
    • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    使用方法については ハンズオン実行用の Docker image の使い方 を参照のこと.

    SSH

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する (環境構築 を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    python
    class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    • まず最初に,VPC を定義する.

    • 次に, security group (SG) を定義している. ここでは,任意の IPv4 のアドレスからの,ポート 22 (SSH の接続に使用される)への接続を許可している. それ以外の接続は拒絶される.

    • 最後に,上記で作った VPC と SG が付与された EC2 インスタンスを作成している. インスタンスタイプは t2.micro を選択し, Amazon Linux を OS として設定している.

    それぞれについて,もう少し詳しく説明しよう.

    VPC (Virtual Private Cloud)

    VPC のアイコン.

    VPC

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    python
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

    • cidr="10.10.0.0/23" : このパラメータは,VPC 内の IPv4 のレンジを指定している. CIDR 記法については, Wikipediaなどを参照. 10.10.0.0/2310.10.0.0 から 10.10.1.255 までの 512 個の連続したアドレス範囲を指している. つまり,この VPC では最大で 512 個のユニークな IPv4 アドレスが使えることになる. 今回はサーバーは一つなので 512 個は明らかに多すぎるが,VPC はアドレスの数はどれだけ作成しても無料なので,多めに作成した.

    • subnet_configuration=... : このパラメータは,VPC にどのようなサブネットを作るか,を決めている. サブネットの種類には private subnetpublic subnet の二種類がある. private subnet は基本的にインターネットとは遮断されたサブネット環境である. インターネットと繋がっていないので,セキュリティは極めて高く, VPC 内のサーバーとのみ通信を行えばよい EC2 インスタンスはここに配置する. Public subnet とはインターネットに繋がったサブネットである. 本ハンズオンで作成するサーバーは,外から SSH でログインを行いたいので, Public subnet 内に配置する. より詳細な記述は 公式ドキュメンテーション を参照.

    • natgateways=0 : これは少し高度な内容なので省略する (興味のある読者は 公式ドキュメンテーションを参照). が,これを 0 にしておかないと,NAT Gateway の利用料金が発生してしまうので,注意!

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    python
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    EC2 (Elastic Compute Cloud)

    EC2 のアイコン.

    EC2

    EC2 は AWS 上に仮想サーバーを立ち上げるサービスである. 個々の起動状態にある仮想サーバーのことをインスタンス (instance) とよぶ (しかし,口語的なコミュニケーションにおいては,サーバーとインスタンスという言葉は相互互換的に用いられることが多い).

    EC2 では用途に応じて様々なインスタンスタイプが提供されている. table_title に,代表的なインスタンスタイプの例を挙げる (執筆時点での情報). EC2 のインスタンスタイプのすべてのリストは 公式ドキュメンテーション "Amazon EC2 Instance Types" で見ることができる.

    EC2 instance types
    InstancevCPUMemory (GiB)Network bandwidth (Gbps)Price per hour ($)

    t2.micro

    1

    1

    -

    0.0116

    t2.small

    1

    2

    -

    0.023

    t2.medium

    2

    4

    -

    0.0464

    c5.24xlarge

    96

    192

    25

    4.08

    c5n.18xlarge

    72

    192

    100

    3.888

    x1e.16xlarge

    64

    1952

    10

    13.344

    table_title からわかるように, CPU は 1 コアから 96 コアまで,メモリーは 1GB から 2TB 以上まで,ネットワーク帯域は最大で 100Gbps まで,幅広く選択することができる. また,時間あたりの料金は,CPU・メモリーの占有数にほぼ比例する形で増加する. EC2 はサーバーの起動時間を秒単位で記録しており,利用料金は使用時間に比例する形で決定される. 例えば, t2.medium のインスタンスを 10 時間起動した場合,0.0464 * 10 = 0.464 ドルの料金が発生する.

    AWS には 無料利用枠 というものがあり, t2.micro であれば月に 750 時間までは無料で利用することができる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    python
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, Hands-on #2: AWS でディープラーニングを実践 でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    さて,ハンズオンのコードの理解ができたところで,プログラムを実際に実行してみよう.繰り返しになるが, 準備 での準備ができていることが前提である.

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    sh
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は Python クイックガイド に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    AWS のシークレットキーをセットする

    AWS CLI および AWS CDK を使うには, AWS のシークレットキーが設定されている必要がある. シークレットキーの発行については AWS のシークレットキーの作成 を参照のこと. シークレットキーを発行したら, AWS CLI のインストール を参照し,コマンドラインの設定を行う.

    手順をここに短く要約すると,一つ目の方法は AWS_ACCESS_KEY_ID などの環境変数を設定するやり方である. もう一つの方法は, ~/.aws/credentials に認証情報を保存しておく方式である. シークレットキーの設定は AWS CLI/CDK を使用するうえで共通のステップになるので,しっかりと理解しておくように.

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    sh
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    sh
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    おめでとう!これで,めでたく AWS 上に EC2 仮想サーバーを起動し,リモートからアクセスできるようになった!

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    sh
    $ cat /proc/cpuinfo
    -
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    $ cat /proc/cpuinfo
    -
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    sh
    $  top -n 1
    -
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    -
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    -
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    -
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    sh
    $ sudo yum update -y
    -$ sudo yum install -y python36
    $ sudo yum update -y
    -$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    sh
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    EC2 コンソール画面

    コンソール右上で,正しいリージョン (今回の場合は ap-northeast-1, Tokyo) が選択されているか,注意する!

    前章で CloudFormation について触れたが,今回デプロイしたアプリケーションも,CloudFormation のスタックとして管理されている. スタック (stack) とは, AWS リソースの集合のことを指す. 今回の場合は, VPC/EC2/SG などがスタックの中に含まれている. コンソールで CloudFormation のページに行ってみよう (figure_title).

    CloudFormation コンソール画面

    "MyFirstEc2" という名前のスタックがあることが確認できる. クリックをして中身を見てみると,EC2, VPC などのリソースがこのスタックに紐付いていることがわかる.

    スタックを削除

    これにて,第一回のハンズオンで説明すべき事柄はすべて完了した. 最後に,使わなくなったスタックを削除しよう. スタックの削除には,二つの方法がある.

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    ここまでが,本書の第一部の内容である. 盛りだくさんの内容であったが,ついてこれたであろうか?

    クラウド概論 では,クラウドの定義と用語の説明を行ったあと,なぜクラウドを使うのか,という点を議論した. 続いて AWS 入門 では,クラウドを学ぶ具体的なプラットフォームとして AWS を取り上げ, AWS を使用するにあたり最低限必要な知識と用語の説明を行った. さらに, Hands-on #1: 初めての EC2 インスタンスを起動する のハンズオンでは AWS CLI と AWS CDK を使って,自身のプライベートなサーバーを AWS 上に立ち上げる演習を行った.

    これらを通じて,いかに簡単に (たった数行のコマンドで!) 仮想サーバーを立ち上げたり,削除したりすることができるか,体験できただろう. 筆者は,クラウド概論 でクラウドの最も重要な側面はダイナミックに計算リソースを拡大・縮小できることである,と述べた. この言葉の意味が,ハンズオンを通じてより明らかになっただろうか? ここで学んだ技術を少し応用するだけで,自分のウェブページをホストする仮想サーバーを作成したり,大量のコアを搭載した EC2 インスタンスを用意して科学計算を実行するなど,いろいろなアプリケーションが実現できる.

    次章からは,今回学んだクラウドの技術を基に,より現実に即した問題を解くことを体験してもらう. お楽しみに!

    クラウドで行う科学計算・機械学習

    計算機が発達した現代では,計算機によるシミュレーションやビッグデータの解析は,科学・エンジニアリングの研究の主要な柱である. これらの大規模な計算を実行するには,クラウドは最適である. 本章から始まる第二部では,どのようにしてクラウド上で科学計算を実行するのかを,ハンズオンとともに体験してもらう. 科学計算の具体的な題材として,今回は機械学習(深層学習)を取り上げる.

    なお,本書では PyTorch ライブラリを使って深層学習のアルゴリズムを実装するが,深層学習および PyTorch の知識は不要である. 講義ではなぜ・どうやって深層学習をクラウドで実行するかに主眼を置いているので,実行するプログラムの詳細には立ち入らない. 将来,自分で深層学習を使う機会が来たときに,詳しく学んでもらいたい.

    なぜ機械学習をクラウドで行うのか?

    2010 年頃に始まった第三次 AI ブームのおかげで,学術研究だけでなく社会・ビジネスの文脈でも機械学習に高い関心が寄せられている. とくに,深層学習 (ディープラーニング) とよばれる多層のレイヤーからなるニューラルネットワークを用いたアルゴリズムは,画像認識や自然言語処理などの分野で圧倒的に高い性能を実現し,革命をもたらしている.

    深層学習の特徴は,なんといってもそのパラメータの多さである. 層が深くなるほど,層間のニューロンを結ぶ重みパラメータの数が増大していく. たとえば,最新の言語モデルである GPT-3 には1750 億個ものパラメータが含まれている. このような膨大なパラメータを有することで,深層学習は高い表現力と汎化性能を実現しているのである.

    GPT-3 に限らず,最近の SOTA (State-of-the-art) の性能を達成するニューラルネットワークでは,百万から億のオーダーのパラメータを内包することは頻繁になってきている. そのような巨大なニューラルネットを訓練 (最適化) させるのは,当然のことながら膨大な計算コストがかかる. 結果として,ひとつの計算機では丸一日以上の時間がかかる場合も珍しくない. 深層学習の発展の速度は目覚ましく,研究・ビジネス両方の観点からも,いかにスループットよくニューラルネットワークの最適化を行えるかが鍵となってくる. そのような問題を解決するのにとても有効な手段が,クラウドである! Hands-on #1: 初めての EC2 インスタンスを起動する でその片鱗を見たように,クラウドを使用することでゼロから数千に至るまでの数のインスタンスを動的に起動し,並列に計算を実行することができる. さらに,深層学習を加速させる目的で,深層学習の演算に専用設計された計算チップ (GPU など) がある. クラウドを利用すると,そのような専用計算チップも無尽蔵に利用することができる. 事実,先述した GPT-3 の学習も,詳細は明かされていないが,Microsoft 社のクラウドを使って行われたと報告されている.

    GPU による深層学習の高速化

    深層学習の計算で欠かすことのできない技術として, GPU (Graphics Processing Unit) について少し説明する.

    GPU は,その名のとおり,元々はコンピュータグラフィックスを出力するための専用計算チップである. CPU (Central Processing Unit) に対し,グラフィックスの演算に特化した設計がなされている. 身近なところでは, XBox や PS5 などのゲームコンソールなどに搭載されているし,ハイエンドなノート型・デスクトップ型計算機にも搭載されていることがある. コンピュータグラフィックスでは,スクリーンにアレイ状に並んだ数百万個の画素をビデオレート (30 fps) 以上で処理する必要がある. そのため,GPU はコアあたりの演算能力は比較的小さいかわりに,チップあたり数百から数千のコアを搭載しており (figure_title),スクリーンの画素を並列的に処理することで,リアルタイムでの描画を実現している.

    GPUのアーキテクチャ.GPUには数百から数千の独立した計算コアが搭載されている. (画像出典: https://devblogs.nvidia.com/nvidia-turing-architecture-in-depth/)

    このように,コンピュータグラフィクスの目的で生まれた GPU だが,2010 年前後から,その高い並列計算能力をグラフィックス以外の計算 (科学計算など) に用いるという流れ (General-purpose computing on GPU; GPGPU) が生まれた. GPU のコアは,その設計から,行列の計算など,単純かつ規則的な演算が得意であり,そのような演算に対しては数個程度のコアしかもたない CPU に比べて圧倒的に高い計算速度を実現することができる. 現在では GPGPU は分子動力学や気象シミュレーション,そして機械学習など多くの分野で使われている.

    ディープラーニングで最も頻繁に起こる演算が,ニューロンの出力を次の層のニューロンに伝える畳み込み (Convolution) 演算である (figure_title). 畳み込み演算は,まさに GPU が得意とする演算であり, CPU ではなく GPU を用いることで学習を飛躍的に (最大で数百倍程度) 加速させることができる.

    ニューラルネットワークにおける畳み込み演算.

    このように GPU は機械学習の計算で欠かせないものであるが,なかなか高価である. たとえば,科学計算・機械学習に専用設計された NVIDIA 社の Tesla V100 というチップは,一台で約百万円の価格が設定されている. 機械学習を始めるのに,いきなり百万円の投資はなかなか大きい. だが,クラウドを使えば,初期コスト0で GPU を使用することができる.

    機械学習を行うのに, V100 が必ずしも必要というわけではない. むしろ,研究者などでしばしば行われるのは,コンピュータゲームに使われるグラフィックス用の GPU を買ってきて (NVIDIA GeForce シリーズなど),開発のときはをそれを用いる,というアプローチである. グラフィックス用のいわゆる"コンシューマ GPU"は,市場の需要が大きいおかげで,10 万円前後の価格で購入することができる. V100 と比べると,コンシューマ GPU はコアの数が少なかったり,メモリーが小さかったりなどで劣る点があるが, それらを除いては計算能力にとくに制限があるわけではなく,開発の段階では十分な性能である場合がほとんどである. プログラムができあがって,ビッグデータの解析や,モデルをさらに大きくしたいときなどに,クラウドは有効だろう.

    クラウドで GPU を使うには, GPU が搭載された EC2 インスタンスタイプ (P3, P2, G3, G4 など) を選択しなければならない. table_title に,代表的な GPU 搭載のインスタンスタイプを挙げる (執筆時点での情報).

    GPUを搭載したEC2インスタンスタイプ
    InstanceGPUsGPU modelGPU Mem (GiB)vCPUMem (GiB)Price per hour ($)

    p3.2xlarge

    1

    NVIDIA V100

    16

    8

    61

    3.06

    p3n.16xlarge

    8

    NVIDIA V100

    128

    64

    488

    24.48

    p2.xlarge

    1

    NVIDIA K80

    12

    4

    61

    0.9

    g4dn.xlarge

    1

    NVIDIA T4

    16

    4

    16

    0.526

    table_title からわかるとおり, CPU のみのインスタンスと比べると少し高い価格設定になっている. また,古い世代の GPU (V100 に対しての K80) はより安価な価格で提供されている. 1 インスタンスあたりの GPU の搭載数は 1 台から最大で 8 台まで選択することが可能である.

    GPU を搭載した一番安いインスタンスタイプは, g4dn.xlarge であり,これには廉価かつ省エネルギー設計の NVIDIA T4 が搭載されている. 後のハンズオンでは,このインスタンスを使用して,ディープラーニングの計算を行ってみる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    V100 を一台搭載した p3.2xlarge の利用料金は一時間あたり $3.06 である. V100 が約百万円で売られていることを考えると,約 3000 時間 (= 124 日間),通算で計算を行った場合に,クラウドを使うよりも V100 を自分で買ったほうがお得になる,という計算になる (実際には,自前で V100 を用意する場合は, V100 だけでなく, CPU やネットワーク機器,電気使用料も必要なので,百万円よりもさらにコストがかかる).

    GPT-3 で使われた計算リソースの詳細は論文でも明かされていないのだが, Lambda 社のブログで興味深い考察が行われている (Lambda 社は機械学習に特化したクラウドサービスを提供している).

    記事によると,1750 億のパラメータを訓練するには,一台の GPU (NVIDIA V100) を用いた場合,342 年の月日と 460 万ドルのクラウド利用料が必要となる,とのことである. GPT-3 のチームは,複数の GPU に処理を分散することで現実的な時間のうちに訓練を完了させたのであろうが,このレベルのモデルになってくるとクラウド技術の限界を攻めないと達成できないことは確かである.

    深層学習を詳しく勉強したい人には以下の参考書を推薦したい. 深層学習の基礎的な概念や理論は普遍的であるが,この分野は日進月歩なので,常に最新の情報を取り入れることを忘れずに.

    Hands-on #2: AWS でディープラーニングを実践

    準備

    ハンズオン第二回では, GPU を搭載した EC2 インスタンスを起動し,深層学習モデルの学習と推論を実行する演習を行う.

    ハンズオンのソースコードは GitHub の handson/mnist に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. それ以外に必要な準備はない.

    初期状態の AWS アカウントでは, GPU 搭載の G タイプのインスタンスの起動上限が 0 になっていることがある. これを確認するには, AWS コンソールから EC2 の画面を開き,左のメニューから Limits を選択する. その中の Running On-Demand All G instances という数字が G インスタンスの起動上限を表している.

    もし,これが 0 になっていた場合は, AWS の自動申請フォームから上限緩和のリクエストを送る必要がある. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,東京 (ap-northeast-1) リージョンでは 0.71 $/hour のコストが発生する.

    AWS Educate Starter Account を使用している読者へ: 執筆時点においては, Starter Account には GPU 搭載型インスタンスを起動できないという制限が設けられている. したがって, Starter Account のユーザーはこのハンズオンを実行することはできない. 興味のある読者は,制限のない一般アカウントを自分自身で取得する必要があることに注意.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#2で作製するアプリケーションのアーキテクチャ

    図の多くの部分が,第一回ハンズオンで作成したアプリケーションと共通していることに気がつくだろう. 少しの変更で,簡単にディープラーニングを走らせる環境を構築することができるのである!主な変更点は次の3点である.

    • GPU を搭載した g4dn.xlarge インスタンスタイプを使用

    • ディープラーニングに使うプログラムがあらかじめインストールされた DLAMI (後述) を使用

    • SSH にポートフォワーディングのオプションつけてサーバーに接続し,サーバーで起動している Jupyter Notebook (後述) を使ってプログラムを書いたり実行したりする

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    python
    class Ec2ForDl(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class Ec2ForDl(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, クラウドで行う科学計算・機械学習 ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

    • ここでは,Deep Learning 用の諸々のソフトウェアがプリンストールされた AMI (Deep Learning Amazon Machine Image; DLAMI) を選択している (第一回では,Amazon Linux という AMI を使用していた). 使用する AMI の ID は リージョンごとに指定する必要があり,ここでは us-east-1ap-northeast-1 でそれぞれ定義している.

    DLAMI という新しい概念が出てきたので,説明しよう.

    AMI が us-east-1ap-northeast-1 でしか定義されていないので,提供されているコードはこの二つのリージョンのみでデプロイ可能である. もしほかのリージョンを利用したい場合は, AMI の ID を自身で検索し,コードに書き込む必要がある.

    DLAMI (Deep Learning Amazon Machine Image)

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    最も low-level なレイヤーとしては, GPU ドライバー がインストールされている. GPU ドライバーなしには OS は GPU とコマンドのやり取りをすることができない. 次のレイヤーが CUDAcuDNN である. CUDA は, NVIDIA 社が開発した, GPU 上で汎用コンピューティングを行うための言語であり, C++ 言語を拡張したシンタックスを備える. cuDNN は CUDA で書かれたディープラーニングのライブラリであり,n 次元の畳み込みなどの演算が実装されている. ここまでが, "Base" とよばれるタイプの DLAMI の中身である.

    これに加えて, "Conda" とよばれるタイプには, "Base" のプログラム基盤の上に, TensorFlowPyTorch などのライブラリがインストールされている. さらに, Anaconda による仮想環境を使うことによって, TensorFlow の環境・ PyTorch の環境・ MxNet の環境など,フレームワークを簡単に切り替えることができる (これについては,後のハンズオンで触れる). また, Jupyter Notebook もインストール済みである.

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    -
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name \${KEY_NAME} --query 'KeyMaterial' --output text > \${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    -
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    SSH ログインコマンドの <IP address> 部分は自身のインスタンスの IP アドレスを代入することを忘れずに.

    本書の提供している Docker を使ってデプロイを実行した人へ

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    Jupyter Notebook とは,インタラクティブに Python のプログラムを書いたり実行したりするためのツールである. Jupyter は GUI としてウェブブラウザを介してアクセスする形式をとっており,まるでノートを書くように,プロットやテーブルのデータも美しく表示することができる (figure_title). Python に慣れている読者は,きっと一度は使ったことがあるだろう.

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    sh
    $ cd ~ # go to home directory
    -$ jupyter notebook
    $ cd ~ # go to home directory
    -$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    Jupyter Notebook の使い方 (超簡易版)

    • Shift + Enter: セルを実行

    • Esc: Command mode に遷移

    • メニューバーの "+" ボタン または Command mode で A ⇒ セルを追加

    • メニューバーの "ハサミ" ボタン または Command mode で X ⇒ セルを削除

    ショートカットの一覧などは Ventsislav Yordanov 氏によるブログ が参考になる.

    PyTorch はじめの一歩

    PyTorch は Facebook AI Research LAB (FAIR) が中心となって開発を進めている,オープンソースのディープラーニングのライブラリである. PyTorch は 有名な例で言えば Tesla 社の自動運転プロジェクトなどで使用されており,執筆時点において最も人気の高いディープラーニングライブラリの一つである. 本ハンズオンでは, PyTorch を使ってディープラーニングの実践を行う.

    PyTorch の歴史のお話

    Facebook は PyTorch のほかに Caffe2 とよばれるディープラーニングのフレームワークを開発していた (初代 Caffe は UC Berkley の博士課程学生だった Yangqing Jia によって創られた). Caffe2 は 2018 年に PyTorch プロジェクトに合併された.

    また,2019 年 12 月,日本の Preferred Networks 社が開発していた Chainer も開発を終了し,PyTorch の開発チームと協業していくことが発表された (詳しくは プレスリリース を参照). PyTorch には,開発統合前から Chainer からインスパイアされた API がいくつもあり, Chainer の DNA は今も PyTorch に引き継がれているのである…!

    本格的なディープラーニングの計算に移る前に, PyTorch ライブラリを使って, GPU で計算を行うとはどういうものか,その入り口に触れてみよう.

    まずは,新しいノートブックを作成する. Jupyter のホーム画面の右上の "New" を押し,"conda_pytorch_p36" という環境を選択したうえで,新規ノートブックを作成する (figure_title). "conda_pytorch_p36" の仮想環境には, PyTorch がインストール済みである.

    新規ノートブックの作成. "conda_pytorch_p36" の環境を選択する.

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    python
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    python
    x = torch.rand(3,3)
    -print(x)
    x = torch.rand(3,3)
    -print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    python
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    python
    z = x + y
    -print(z)
    z = x + y
    -print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    python
    z = z.to("cpu")
    -print(z)
    z = z.to("cpu")
    -print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    完成した Jupyter Notebook は /handson/mnist/pytorch/pytorch_get_started.ipynb にある. Jupyter の画面右上の "Upload" からこのファイルをアップロードして,コードを走らせることが可能である.

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    python
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -
    -%time z = torch.matmul(x,y)
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -
    -%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    python
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    -
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    -
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    このベンチマークでは, dtype=torch.float32 と指定することで,32bit の浮動小数点型を用いている. ディープラーニングの学習および推論の計算には,32bit 型,場合によっては 16bit 型が使われるのが一般的である. これの主な理由として,教師データやミニバッチに起因するノイズが,浮動小数点の精度よりも大きいことがあげられる. 32bit/16bit を採用することで,メモリー消費を抑えたり,計算速度の向上が達成できる.

    上記のベンチマークから,GPU を用いることで,約 10 倍のスピードアップを実現することができた. スピードアップの性能は,演算の種類や行列のサイズに依存する. 行列積は,そのなかでも最も速度向上が見込まれる演算の一つである.

    実践ディープラーニング! MNIST 手書き数字認識タスク

    ここまで,AWS 上でディープラーニングの計算をするための概念や前提知識をながながと説明してきたが,ついにここからディープラーニングの計算を実際に走らせてみる.

    ここでは,機械学習のタスクで最も初歩的かつ有名な MNIST データセットを使った数字認識を扱う (figure_title). これは,0 から 9 までの手書きの数字の画像が与えられ,その数字が何の数字なのかを当てる,というシンプルなタスクである.

    MNIST 手書き数字データセット

    今回は, MNIST 文字認識タスクを,畳み込みニューラルネットワーク (Convolutional Neural Network; CNN) を使って解く. ソースコードは /handson/minist/pytorch/ にある mnist.ipynbsimple_mnist.py である. なお,このプログラムは, PyTorch の公式 Example Project 集 を参考に,多少の改変を行ったものである.

    まずは,カスタムのクラスや関数が定義された simple_mnist.py をアップロードしよう (figure_title). 画面右上の "Upload" ボタンをクリックし,ファイルを選択することでアップロードができる. この Python プログラムの中に,CNN のモデルや,学習の各イテレーションにおけるパラメータの更新などが記述されている. 今回はこの中身を説明することはしないが,興味のある読者は自身でソースコードを読んでみるとよい.

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    python
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    -
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    -
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    python
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    -
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    -
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    -
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    -
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    python
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    -
    -print("Example data size:", example_data.shape)
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    -
    -print("Example data size:", example_data.shape)
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    python
    model = Model()
    -model.to("cuda") # load to GPU
    model = Model()
    -model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    python
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\\n")
    -
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\\n")
    -
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    python
    model.eval()
    -
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    model.eval()
    -
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は スタックを削除 参照).

    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    Docker 入門

    ここまでの章で扱ってきたハンズオンでは,単一のサーバーを立ち上げ,それに SSH でログインをして,コマンドを叩くことで計算を行ってきた. いわば,パーソナルコンピュータの延長のような形でクラウドを使ってきたわけである. このような,インターネットのどこからでもアクセスできるパーソナルコンピュータとしてのクラウドという使い方も,もちろん便利であるし,いろいろな応用の可能性がある. しかし,これだけではクラウドの本当の価値は十分に発揮されていないと言うべきだろう. クラウド概論 で述べたように,現代的なクラウドの一番の強みは自由に計算機の規模を拡大できることにある. すなわち,多数のサーバーを同時に起動し,複数のジョブを分散並列的に実行させることで大量のデータを処理してこそ,クラウドの本領が発揮されるのである.

    本章からはじまる 3 章分 (Docker 入門, Hands-on #3: AWS で自動質問回答ボットを走らせる, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) を使って,クラウドを利用することでどのように大規模な計算システムを構築しビッグデータの解析に立ち向かうのか,その片鱗をお見せしたい. とくに,前章で扱った深層学習をどのようにビッグデータに適用していくかという点に焦点を絞って議論していきたい. そのための前準備として,本章では Docker とよばれる計算機環境の仮想化ソフトウェアを紹介する (figure_title). 現代のクラウドは Docker なしには成り立たないといっても過言ではないだろう. クラウドに限らず,ローカルで行う計算処理にも Docker は大変便利である. AWS からは少し話が離れるが,しっかりと理解して前に進んでもらいたい.

    機械学習の大規模化

    先ほどから"計算システムの大規模化"と繰り返し唱えているが,それは具体的にはどのようなものを指しているのか? ここでは大規模データを処理するための計算機システムを,機械学習を例にとって見てみよう.

    クラウドで行う科学計算・機械学習 で紹介した GPT-3 のような,超巨大な数のパラメータを有する深層学習モデルを学習させたいとしよう. そのような計算を行いたい場合,一つのサーバーでは計算力が到底足りない. したがって,典型的には figure_title に示すような計算システムの設計がなされる. すなわち,大量の教師データを小さなチャンクとして複数のマシンに分散し,並列的にニューラルネットのパラメータを最適化していくという構造である.

    複数の計算機を使った大規模な深層学習モデルの訓練

    あるいは,学習済みのモデルを大量のデータに適用し,解析を行いたいとしよう. たとえば, SNS のプラットフォームで大量の画像が与えられて,それぞれの写真に何が写っているのかをラベルづけする,などのアプリケーションを想定できる. そのような場合は, figure_title のようなアーキテクチャが考えられるだろう. すなわち,大量のデータを複数のマシンで分割し,それぞれのマシンで推論の計算を行うというような構造である.

    複数の計算機による深層学習モデルを使った推論計算

    このような複数の計算機を同時に走らせるようなアプリケーションをクラウド上で実現するには,どのようにすればよいのだろうか?

    重要なポイントとして, figure_titlefigure_title で起動している複数のマシンは,基本的に全く同一の OS・計算環境を有している点である. ここで,個人のコンピュータで行うようなインストールの操作を,各マシンで行うこともできるが,それは大変な手間であるし,メンテナンスも面倒だろう. すなわち,大規模な計算システムを構築するには,簡単に計算環境を複製できるような仕組みが必要であるということがわかる.

    そのような目的を実現するために使われるのが, Docker とよばれるソフトウェアである.

    Docker とは

    Docker のアイコン

    Docker とは, コンテナ (Container) とよばれる仮想環境下で,ホスト OS とは独立した別の計算環境を走らせるためのソフトウェアである. Docker を使うことで, OS を含めたすべてのプログラムをコンパクトにパッケージングすることが可能になる (パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ). Docker を使うことで,クラウドのサーバー上に瞬時に計算環境を複製することが可能になり, figure_title で見たような複数の計算機を同時に走らせるためのシステムが実現できる.

    Docker は 2013 年に Solomon Hykes らを中心に開発され,それ以降爆発的に普及し,クラウドコンピューティングだけでなく,機械学習・科学計算の文脈などでも欠かすことのできないソフトウェアとなった. Docker はエンタープライズ向けの製品を除き無料で使用することができ,コアの部分は オープンソースプロジェクト として公開されている. Docker は Linux, Windows, Mac いずれの OS でも提供されている. 概念としては, Docker は仮想マシン (Virtual machine; VM) にとても近い. ここでは, VM との対比をしながら,Docker とはなにかを簡単に説明しよう.

    仮想マシン (VM) とは,ホストとなるマシンの上に,仮想化された OS を走らせる技術である (figure_title). VM には ハイパーバイザー (Hypervisor) とよばれるレイヤーが存在する. Hypervisor はまず,物理的な計算機リソース (CPU, RAM, network など) を分割し,仮想化する. たとえば, ホストマシンに物理的な CPU が 4 コアあるとして,ハイパーバイザーはそれを (2,2) 個の組に仮想的に分割することができる. VM 上で起動する OS には,ハイパーバイザーによって仮想化されたハードウェアが割り当てられる. VM 上で起動する OS は基本的に完全に独立であり,たとえば OS-A は OS-B に割り当てられた CPU やメモリー領域にアクセスすることはできない (これを isolation とよぶ). VM を作成するための有名なソフトウェアとしては, VMwareVirtualBoxXen などがある. また,これまで触ってきた EC2 も,基本的に VM 技術を使うことで所望のスペックをもった仮想マシンがユーザーに提示される.

    Docker も, VM と同様に,仮想化された OS をホストの OS 上に走らせるための技術である. VM に対し, Docker ではハードウェアレベルの仮想化は行われておらず,すべての仮想化はソフトウェアレベルで実現されている (figure_title). Docker で走る仮想 OS は,多くの部分をホストの OS に依存しており,結果として非常にコンパクトである. その結果, Docker で仮想 OS を起動するために要する時間は, VM に比べて圧倒的に早い. また, パッケージ化された環境 (=イメージ) のサイズも完全な OS に比べ圧倒的に小さくなるので,ネットワークを通じたやり取りが非常に高速化される点も重要である 加えて, VM のいくつかの実装では,メタル (仮想化マシンに対して,物理的なハードウェア上で直接起動する場合のこと) と比べ,ハイパーバイザーレイヤーでのオーバーヘッドなどにより性能が低下することが知られているが, Docker ではメタルとほぼ同様の性能を引き出すことができるとされている.

    その他, VM との相違点などはたくさんあるのだが,ここではこれ以上詳細には立ち入らない. 大事なのは, Docker とはとてもコンパクトかつハイパフォーマンスな仮想計算環境を作るツールである,という点である. その手軽さゆえに,2013 年の登場以降,クラウドシステムでの利用が急速に増加し,現代のクラウドでは欠くことのできない中心的な技術になっている.

    Docker (左) と VM (右) の比較 (画像出典: https://www.docker.com/blog/containers-replacing-virtual-machines/)

    職業的プログラマーにとっての"三種の神器"とはなんだろうか? 多様な意見があると思うが,筆者は Git, Vim そして Docker を挙げたい.

    Git は多くの読者がご存じの通り,コードの変更を追跡するためのシステムである. Linux の作成者である Linus Torvalds によって 2005 年に誕生した. チームでの開発を進める際には欠かせないツールだ.

    Vim は 1991 年から 30 年以上の間プログラマーたちに愛されてきたテキストエディターである. Stackoverflow が行った 2019 年のアンケート によると,開発環境の部門で 5 位の人気を獲得している. たくさんのショートカットと様々なカスタム設定が提供されているので,初見の人にはなかなかハードルが高いが,一度マスターすれば他のモダンなエディターや統合開発環境に負けない,あるいはそれ以上の開発体験を実現することができる.

    これらの十年以上の歴史あるツールに並んで,第三番目の三種の神器として挙げたいのが Docker だ. Docker はプログラマーの開発のワークフローを一変させた. たとえば,プロジェクトごとに Docker イメージを作成することで,どの OS・コンピュータ でも全く同じ計算環境で開発・テストを実行することができるようになった. また, DevOpsCI / CD (Continuous Integration / Continuous Deployment) といった最近の開発ワークフローも Docker のようなコンテナ技術の存在に立脚している. さらにはサーバーレスコンピューティング (Serverless architecture) といった概念も,コンテナ技術の生んだ大きな技術革新といえる.

    あなたにとっての三種の神器はなんだろうか? また,これからの未来ではどんな新しいツールが三種の神器としてプログラマーのワークフローを革新していくだろうか?

    Docker チュートリアル

    Docker とはなにかを理解するためには,実際に触って動かしてみるのが一番有効な手立てである. ここでは, Docker の簡単なチュートリアルを行っていく.

    Docker のインストールについては, Docker のインストール および 公式のドキュメンテーション を参照してもらいたい. Docker のインストールが完了している前提で,以下は話を進めるものとする.

    Docker 用語集

    Docker を使い始めるに当たり,最初に主要な用語を解説しよう. 次のパラグラフで太字で強調された用語を頭に入れた上で,続くチュートリアルに取り組んでいただきたい.

    Docker を起動する際の大まかなステップを示したのが figure_title である. パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ. イメージは, Docker Hub などのリポジトリで配布されているものをダウンロードするか,自分でカスタムのイメージを作成することも可能である. イメージを作成するための”レシピ”を記述したファイルが Dockerfile である. Dockerfile からイメージを作成する操作を build とよぶ. イメージがホストマシンのメモリにロードされ,起動状態にある計算環境のことを コンテナ (Container) とよぶ. Container を起動するために使用されるコマンドが run である.

    Image と Container

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, Hands-on #2: AWS でディープラーニングを実践 でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    sh
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    python
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    -
    -RUN apt-get update \\
    -    && apt-get install nano
    -
    -#
    -RUN cd /opt \\
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \\
    -    && tar -xzf Python-3.7.6.tgz \\
    -    && cd Python-3.7.6 \\
    -    && ./configure --enable-optimizations \\
    -    && make install
    -
    -RUN cd /opt \\
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \\
    -    && unzip awscliv2.zip \\
    -    && ./aws/install
    -
    -#
    -RUN npm install -g aws-cdk@1.100
    -
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    -
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    -
    -RUN apt-get update \\
    -    && apt-get install nano
    -
    -#
    -RUN cd /opt \\
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \\
    -    && tar -xzf Python-3.7.6.tgz \\
    -    && cd Python-3.7.6 \\
    -    && ./configure --enable-optimizations \\
    -    && make install
    -
    -RUN cd /opt \\
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \\
    -    && unzip awscliv2.zip \\
    -    && ./aws/install
    -
    -#
    -RUN npm install -g aws-cdk@1.100
    -
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    -
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    Singularity は科学計算や HPC (High Performance Computing) の分野で人気の高いコンテナプラットフォームである. Singularity では大学・研究機関の HPC クラスターでの運用に適したような設計が施されている. たとえば, Docker は基本的には root 権限で実行されるのに対し, Singularity はユーザー権限 (コマンドを実行したユーザー自身) でプログラムが実行される. root 権限での実行は Web サーバーのように個人・企業がある特定のサービスのために運用するサーバーでは問題ないが,多数のユーザーが多様な目的で計算を実行する HPC クラスターでは問題となる. また,Singularity は独自のイメージの作成方法・エコシステムをもっているが, Docker イメージを Singularity のイメージに変換し実行する機能も有している.

    podman は Red Hat 社によって開発されたもう一つのコンテナプラットフォームである. podman は基本的に Docker と同一のコマンドを採用しているが,実装は Red Hat によってスクラッチから行われた. podman では, Singularity と同様にユーザー権限でのプログラムの実行を可能であり,クラウドおよび HPC の両方の環境に対応するコンテナプラットフォームを目指して作られた. また,その名前にあるとおり pod とよばれる独自の概念が導入されている.

    著者の個人的な意見としては,現時点では Docker をマスターしておけば当面は困ることはないと考えるが,興味のある読者はぜひこれらのツールも試してみてはいかがだろうか?

    Elastic Container Service (ECS)

    ECS のアイコン

    ここまでに説明してきたように, Docker を使うことで仮想計算環境を簡単に複製・起動することが可能になる. 本章の最後の話題として, AWS 上で Docker を使った計算システムを構築する方法を解説しよう.

    Elastic Container Service (ECS) とは, Docker を使った計算機クラスターを AWS 上に作成するためのツールである (figure_title). ECS を使用することで, Docker にパッケージされたアプリケーションを計算機クラスターに投入したり,計算機クラスターのインスタンスを追加・削除する操作 (=スケーリング) を行うことができる.

    ECS の概要を示したのが figure_title である. ECS は,タスク (Task) と呼ばれる単位で管理された計算ジョブを受け付ける. システムにタスクが投入されると,ECS は最初にタスクで指定された Docker イメージを外部レジストリからダウンロードしてくる. 外部レジストリとしては, Docker Hub や AWS 独自の Docker レジストリである ECR (Elastic Container Registry) を指定することができる.

    ECS の次の重要な役割はタスクの配置である. あらかじめ定義されたクラスター内で,計算負荷が小さい仮想インスタンスを選び出し,そこに Docker イメージを配置することで指定された計算タスクが開始される. "計算負荷が小さい仮想インスタンスを選び出す" と言ったが,具体的にどのような戦略・ポリシーでこの選択を行うかは,ユーザーの指定したパラメータに従う.

    また,クラスターのスケーリングも ECS における重要な概念である. スケーリングとは,クラスター内のインスタンスの計算負荷をモニタリングし,計算負荷に応じてインスタンスの起動・停止を行う操作を指す. クラスター全体の計算負荷が指定された閾値 (たとえば 80%の稼働率) を超えていた場合,新たな仮想インスタンスをクラスター内に立ち上げる操作を scale-out (スケールアウト) とよび, 負荷が減った場合に不要なインスタンスを停止する操作を scale-in (スケールイン) とよぶ. クラスターのスケーリングは, ECS がほかの AWS のサービスと連携することで実現される. 具体的には, EC2 の Auto scaling group (ASG)Fargate の2つの選択肢が多くの場合選択される. ASG については Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する, Fargate については Hands-on #3: AWS で自動質問回答ボットを走らせる でより詳細に解説する.

    これら一連のタスクの管理を, ECS は自動でやってくれる. クラスターのスケーリングやタスクの配置に関してのパラメータを一度指定してしまえば,ユーザーは (ほとんどなにも考えずに) 大量のタスクを投入することができる. クラスターのスケーリングによってタスクの量にちょうど十分なだけのインスタンスが起動し,タスクが完了した後は不要なインスタンスはすべて停止される.

    さて,ここまで説明的な話が続いてしまったが,次章からは早速 Docker と AWS を使って大規模な並列計算システムを構築していこう!

    ECS の概要

    Hands-on #3: AWS で自動質問回答ボットを走らせる

    ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.

    通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 (Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.

    Fargate

    ハンズオンに入っていく前に, Fargate という AWS の機能を知っておく必要がある (figure_title).

    Fargate のアイコン

    ECS の概要を示した figure_title をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. EC2 あるいは Fargate のいずれかである. EC2 を用いた場合は,先の章 (Hands-on #1: 初めての EC2 インスタンスを起動する, Hands-on #2: AWS でディープラーニングを実践) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 (Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) で説明することにする.

    Fargate とは, ECS での利用に特化して設計された,コンテナを使用した計算タスクを走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は docker run のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.

    Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは 公式ドキュメンテーション "Amazon ECS on AWS Fargate" 参照). クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.

    以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.

    厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.

    準備

    ハンズオンのソースコードは GitHub の handson/qa-bot にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \\"the world's most famous equation\\". He received the 1921 Nobel Prize in Physics \\"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \\"the world's most famous equation\\". He received the 1921 Nobel Prize in Physics \\"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    sh
    answer: 1921
    answer: 1921

    人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

    今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."\n$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."\n$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    sh
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    sh
    $ question="Why did Einstein win the Nobel prize ?"\n$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"\n$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    出力:

    sh
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    今回提供する Q-A ボットの Docker のソースコードは https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile にある.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,以下のような設計である.

    • クライアントは,質問を AWS 上のアプリケーションに送信する.

    • 質問のタスクは ECS によって処理される.

    • ECS は, Docker Hub から,イメージをダウンロードする.

    • 次に,ECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.

      • このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.
    • ジョブが実行される.

    • ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.

    • 最後に,クライアントは DynamoDB から質問への回答を読み取る.

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    sh
    class EcsClusterQaBot(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    -
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    -
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    -
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    -
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    class EcsClusterQaBot(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    -
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    -
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    -
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    -
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

    • ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.

    • ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.

    • ここで,実行するタスクを定義している (task definition).

    • ここで, タスクの実行で使用する Docker イメージを定義している.

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    sh
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    -
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    -
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    -
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    -
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.

    このコードで cpu=1024 と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は 公式ドキュメンテーション "Amazon ECS on AWS Fargate" を参照のこと.

    CPU ユニットと 指定可能なメモリー量の換算表

    CPU ユニット

    メモリーの値

    256 (.25 vCPU)

    0.5 GB, 1 GB, 2 GB

    512 (.5 vCPU)

    1 GB, 2 GB, 3 GB, 4 GB

    1024 (1 vCPU)

    2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB

    2048 (2 vCPU)

    Between 4 GB and 16 GB in 1-GB increments

    4096 (4 vCPU)

    Between 8 GB and 30 GB in 1-GB increments

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. figure_title で, FARGATE という文字の下に 0 Running tasks, 0 Pending tasks と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.

    ECS コンソール画面

    続いて,この画面の左のメニューバーから Task Definitions という項目を見つけ,クリックしよう. 移動した先のページで EcsClusterQaBotEcsClusterQaBotTaskDefXXXX という項目が見つかるので,開く. 開いた先のページをスクロールすると figure_title に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.

    Task definition の確認

    タスクの実行

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, "Tasks" という名前のタブがあるので,それを開く (figure_title). すると,実行中のタスクの一覧が表示されるだろう.

    ECS のタスクの実行状況をモニタリング

    figure_title で見て取れるように, "Last status = Pending" となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.

    しばらく待つうちに, Status が "RUNNING" に遷移し,計算が始まる. 計算が終わると, Status は "STOPPED" に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.

    figure_title の画面から, "Task" の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (figure_title). "Last status", "Platform version" など,タスクの情報が表示されている. また, "Logs" のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.

    質問タスクの実行結果

    さて, run_task.py を実行したコマンドラインに戻ってきてみると, figure_title のような出力が得られているはずである. "Momotaro" という正しい回答が返ってきている!

    質問タスクの実行結果

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する

    ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

    本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

    Auto scaling groups (ASG)

    ハンズオンに入っていく前に, Auto scaling groups (ASG) とよばれる EC2 の概念を知っておく必要がある.

    ECS の概要を示した figure_title を振り返って見てほしい. 前章 (Hands-on #3: AWS で自動質問回答ボットを走らせる) でも説明したが, ECS のクラスターで計算を担う実体としては EC2 と Fargate を指定することができる. Fargate については前章で記述した. Fargate を用いると,自在にスケールする計算環境をとても簡単な設定で構築することができた. しかし, GPU を利用することができないなど,いくつかの制約があった. EC2 を使用した計算環境を指定することで,プログラミングの複雑度は増すが, GPU やその他のより高度かつ複雑な設定を伴ったクラスターを構築することができる.

    EC2 クラスターには ASG と呼ばれるサービスが配置される. ASG は複数の EC2 インスタンスをロジカルな単位でグループ化することでクラスターを構成する. ASG はクラスター内に新しいインスタンスを起動する,あるいは不要になったインスタンスを停止するなどのスケーリングを担う. ASG で重要な概念として, desired capacity, minimum capacity, maximum capacity というパラメータがある. minimum capacity, maximum capacity は,それぞれクラスター内に配置できるインスタンスの数の最小値・最大値を指定するパラメータである. 前者は,クラスターに負荷がかかっていない場合でもアイドリング状態にあるインスタンスを維持することで,急に負荷が増大した時などのバッファーとして作用することができる. 後者は,負荷が急に増えたときに,過剰な数のインスタンスが起動する事態を防ぎ,経済的なコストの上限を定める役割を果たす.

    desired capacity が,その時々でシステムが要求するインスタンスの数を指定する. desired capacity は,例えば 24 時間のリズムに合わせてインスタンスの数を増減させる (昼は多く夜は少なくなど) などの決まったスケジュールに基づいた設定を適用することができる. あるいはクラスター全体にかかっている負荷に応じて, desired capacity を動的に制御することも可能である. どのような基準でクラスターのスケーリングを行うかを定めるルールのことを,スケーリングポリシーとよぶ. たとえば,クラスター全体の稼働率 (負荷) を常に 80% に維持する,などのスケーリングポリシーが想定できる. この場合,クラスター全体の負荷が 80%を下回ったときにはクラスターからインスタンスが削除され,80%を超える (あるいは超えると予測される) 場合はインスタンスを追加する,という操作が ASG によって自動的に行われる.

    上記のようなパラメータを検討し,ユーザーは ASG を作成する. ASG を作成したのち, ECS との連携をプログラムしてあげることで, ECS を介して ASG による EC2 クラスターにタスクを投入することが可能になる.

    AWS Batch

    AWS Batch のアイコン

    先に説明したように, ECS と ASG を組み合わせることで,所望の計算クラスターを構築することが可能である. しかしながら, ECS と ASG にはかなり込み入った設定が必要であり,初心者にとっても経験者にとってもなかなか面倒なプログラミングが要求される. そこで, ECS と ASG によるクラスターの設計を自動化してくれるサービスが提供されている. それが AWS Batch である.

    AWS Batch はその名のとおりバッチ (Batch) 化されたジョブ (入力データだけが異なる独立した演算が繰り返し実行されること) を想定している. 多くの科学計算や機械学習がバッチ計算に当てはまる. たとえば,初期値のパラメータを変えて複数のシミュレーションを走らせる,といったケースだ. AWS Batch を用いることの利点は,クラスターのスケーリングやジョブの割り振りはすべて自動で実行され, ユーザーはクラウドの舞台裏の詳細を気にすることなく,大量のジョブを投入できるシステムが手に入る点である. が,知識として背後では ECS/ASG/EC2 の三つ巴が協調して動作しているという点は知っておいてほしい.

    AWS Batch では,ジョブの投入・管理をスムーズに行うため,次のような概念が定義されている (figure_title). まず, ジョブ (Job) というのが,AWS Batch によって実行される一つの計算の単位である. Job definitions とはジョブの内容を定義するものであり,これには実行されるべき Docker のイメージのアドレスや,割り当てる CPU・RAM の容量,環境変数などの設定が含まれる. Job definition に基づいて個々のジョブが実行される. ジョブが実行されると,ジョブは Job queues に入る. Job queues とは,実行待ち状態にあるジョブの列のことであり,時間的に最も先頭に投入されたジョブが最初に実行される. また,複数の queue を配置し, queue ごとに priority (優先度) を設定することが可能であり, priority の高い queue に溜まったジョブが優先的に実行される (筆者はこれをディズニーランドの"ファストパス"を連想して捉えている). Compute environment とは,先述したクラスターとほぼ同義の概念であり,計算が実行される場所 (EC2 や Fargate からなるクラスター) を指す. Compute environment には,使用する EC2 のインスタンスタイプや同時に起動するインスタンス数の上限などの簡易なスケーリングポリシーが指定されている. Job queues は Compute environment の空き状況を監視しており, それに応じてジョブを Compute environment に投下する.

    以上が AWS Batch を使用するうえで理解しておかなければならない概念であるが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは,実際に自分で手を動かしながら学んでいこう.

    AWS Batch の主要な概念

    EC2 or Fargate?

    ECS でクラスターを構成する際,計算を実行する場として EC2 と Fargate の二つの選択肢があることを説明した. それぞれ長所と短所を抱えているのだが,どのような場合にどちらを使うべきだろうか? それを検討するため,まずは table_title を見てみよう. これは EC2 と Fargate の特徴をまとめたものである. 説明の都合上,大幅な粗視化が行われている点は留意していただきたい.

    EC2 vs Fargate
    EC2Fargate

    Compute capacity

    Medium to large

    Small to medium

    GPU

    Yes

    No

    Launch speed

    Slow

    Fast

    Task placement flexibility

    Low

    High

    Programming complexity

    High

    Low

    これまでに見てきたように, EC2 は最大の CPU 数・メモリーサイズが大きかったり, GPU を利用できたりするなど,単一のインスタンスでの計算能力は高い. 対して, Fargate は単一インスタンスの最大 CPU 数は 4 コアが上限である. その一方で,インスタンスの起動に要する時間は Fargate のほうが圧倒的に早く,より俊敏にクラスターのスケーリングを行うことができる. また,タスクをクラスターに投入する際のフレキシビリティも Fargate のほうが高い. フレキシビリティというのは,例えば一つのインスタンスで 2 つ以上のコンテナを走らせる,などの状況である. 単位 CPU あたりで処理されるタスクの数を最大化する際には,このような設計がしばしば採用される. プログラミングの複雑さという観点からは, Fargate のほうが一般的にシンプルな実装になる.

    このように, EC2 と Fargate は互いに相補的な特性を有しており,アプリケーションによって最適な計算環境は検討される必要がある. また,EC2 と Fargate を両方用いたハイブリッドクラスターというのも定義可能であり,そのような選択肢もしばしば用いられる.

    準備

    ハンズオンのソースコードは GitHub の handson/aws-batch にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,アメリカ東部 (us-east-1) リージョンでは 0.526 $/hour のコストが発生する. 東京 (ap-northeast-1) を選択した場合は 0.71 $/hour のコストが発生する.

    準備 でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, 実践ディープラーニング! MNIST 手書き数字認識タスク で扱った MNIST 手書き文字認識の問題を再度取り上げよう. 実践ディープラーニング! MNIST 手書き数字認識タスク では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    ランダムサーチ法とは,ハイパーパラメータの組をある範囲の中でランダムに抽出し,大量に試行されたランダムな組の中から最適なパラメータの組を見出す方法である. すべての可能性を網羅的に探索できるわけではないが,調整すべきパラメータの数が多数ある場合に,グリッドサーチよりも効率的に広い探索空間をカバーすることができる.

    ベイズ最適化を用いた方法では,過去の探索結果から次にどの組み合わせを探索すべきかという指標を計算し,次に探索するパラメータを決定する. これにより,理論的にはグリッドサーチやランダムサーチ法よりも少ない試行回数で最適なパラメータにたどり着くことができる.

    並列化の観点でいうと,グリッドサーチとランダムサーチは各ハイパーパラメータの組の計算は独立に実行することができるため並列化が容易である. このように独立したジョブとして分割・並列化可能な問題を Embarrassingly parallel な問題とよぶ (直訳すると"恥ずかしいほど並列化可能な問題",ということになる). Embarrassingly parallel な問題はクラウドの強力な計算リソースを用いることで,非常なシンプルな実装で解くことができる. この章ではこのようなタイプの並列計算を取り上げる.

    一方,ベイズ最適化による方法は,過去の結果をもとに次の探索が決定されるので,並列化はそれほど単純ではない. 最近では optuna などのハイパーパラメータ探索のためのライブラリが発達しており,ベイズ最適化の数理的な処理を自動で実行してくれるので便利である. これらのライブラリを使うと,もし一台のコンピュータ (ノード) の中に複数の GPU が存在する場合は,並列に計算を実行することができる. しかしながら,一台のノードにとどまらず,複数のノードをまたいだ並列化は,高度なプログラミングテクニックが必要とされるだけでなく,ノード間の接続様式などクラウドのアーキテクチャにも深く依存するものである. 本書ではここまで高度なクラウドの使用方法には立ち入らない.

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に 実践ディープラーニング! MNIST 手書き数字認識タスク のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    sh
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. Hands-on #2: AWS でディープラーニングを実践 のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    sh
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドでは,--gpus all というパラメータが加わった.

    CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

    (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

    これはオーバーフィッティングとよばれる現象で,ニューラルネットが訓練データに過度に最適化され,訓練データの外のデータに対しての精度 (汎化性能) が向上していないことを示している. このような場合の対処法として, Early stopping とよばれるテクニックが知られている. Early stopping とは,検証データの Loss を追跡し,それが減少から増加に転じるエポックで学習をうち止め,そのエポックでのウェイトパラメータを採用する,というものである. 本ハンズオンでも, Early stopping によって訓練の終了を判断し,モデルの性能評価を行っていく.

    MNIST 手書き文字データセットでは,訓練データとして 60,000 枚,テストデータとして 10,000 枚の画像が与えられている. 本ハンズオンで使用するコードでは,訓練データのうち 80% の 48,000 枚を訓練データとして使用し,残り 20% の 12,000 枚を検証データとして用いている. 詳しくはソースコードを参照のこと.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントは,あるハイパーパラメータの組を指定して Batch にジョブを提出する

    • Batch はジョブを受け取ると, EC2 からなるクラスターで計算を実行する

    • クラスター内では g4dn.xlarge インスタンスが起動する

    • Docker イメージは, AWS 内に用意された ECR (Elastic Container Registry) から取得される

    • 複数のジョブが投下された場合は,その数だけのインスタンスが起動し並列に実行される

    • 各ジョブによる計算の結果は S3 に保存される

    • 最後にクライアントは S3 から結果をダウンロードし,最適なハイパーパラメータの組を決定する

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    python
    class SimpleBatch(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    -
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    -
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    -
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    -
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    -
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    -
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    class SimpleBatch(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    -
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    -
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    -
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    -
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    -
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    -
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    • で,計算結果を保存するための S3 バケットを用意している

    • で, Compute environment を定義している. ここでは g4dn.xlarge のインスタンスタイプを使用するとし,最大の vCPU 使用数は 64 と指定している. また,最小の vCPU は 0 である. 今回は,負荷がかかっていないときにアイドリング状態にあるインスタンスを用意する利点は全くないので,ここは 0 にするのが望ましい.

    • で, <2> で作成した Compute environment と紐付いた Job queue を定義している.

    • で,ジョブが計算結果を S3 に書き込むことができるよう, IAM ロールを定義している. (IAM とはリソースがもつ権限を管理する仕組みである.詳しくは AWS における権限の管理 (IAM) を参照)

    • では, Docker image を配置するための ECR を定義している.

    • で Job definition を作成している. ここでは,4 vCPU, 12000 MB (=12GB) の RAM を使用するように指定している. また,今後必要となる環境変数 (BUCKET_NAME) を設定している. さらに, <4> で作った IAM を付与している.

    g4dn.xlarge は 1 台あたり 4 vCPU が割り当てられている. このプログラムでは Compute environment の maximum vCPUs を 64 と指定しているので,最大で 16 台のインスタンスが同時に起動することになる. ここで maxium vCPUs を 64 に限定しているのは,なんらかのミスで意図せぬジョブを大量にクラスターに投入してしまった事態で,高額の AWS 利用料金が発生するのを防ぐためである. もし,自分のアプリケーションで必要と判断したならば自己責任において 64 よりも大きな数を設定して構わない.

    ここで注意が一点ある. AWS では各アカウントごとに EC2 で起動できるインスタンスの上限が設定されている. この上限は AWS コンソールにログインし, EC2 コンソールの左側メニューバーの Limits をクリックすることで確認できる (figure_title). g4dn.xlarge (EC2 の区分でいうと G ファミリーに属する) の制限を確認するには, Running On-Demand All G instances という名前の項目を見る. ここにある数字が, AWS によって課されたアカウントの上限であり,この上限を超えたインスタンスを起動することはできない. もし,自分の用途に対して上限が低すぎる場合は,上限の緩和申請を行うことができる. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    EC2コンソールから各種の上限を確認する

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    次に,Job queue overview にある SimpleBatch-queue という項目に注目してほしい. ここでは実行待ちのジョブ・実行中のジョブ・実行が完了したジョブを一覧で確認することができる. PENDING, RUNNING, SUCCEEDED, FAILED などのカラムがあることが確認できる.ジョブが進行するにつれて,ジョブの状態がこのカラムにしたがって遷移していく. 後でジョブを実際にサブミットしたときに戻ってこよう.

    最後に,今回作成した Job definition を確認しよう. 左側のメニューから Job definitions を選択し,次の画面で SimpleBatchjob-definition という項目を見つけて開く. ここから Job definition の詳細を閲覧することができる (figure_title). 中でも重要な情報としては, vCPUs, Memory, GPU がそれぞれ Docker に割り当てられる vCPU・メモリー・ GPU の量を規定している. また, Image と書いてあるところに,ジョブで使用される Docker イメージが指定されている. ここでは, ECR のレポジトリを参照している. 現時点ではこの ECR は空である. 次のステップとして,この ECR にイメージを配置する作業を行おう.

    AWS Batch から Job definition を確認

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン (Hands-on #3: AWS で自動質問回答ボットを走らせる) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    python
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    -
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    -
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    • で,新規の ECR を作成している.

    • で Job definition を定義する中で,イメージを <1> で作った ECR から取得するように指定している. これと同時に, Job definition には ECR へのアクセス権限が IAM を通じて自動的に付与される.

    さて,スタックをデプロイした時点では, ECR は空っぽである. ここに自分のアプリケーションで使う Docker イメージを push してあげる必要がある.

    そのために,まずは AWS コンソールから ECR の画面を開こう (検索バーに Elastic Container Registry と入力すると出てくる). Private というタブを選択すると, simplebatch-repositoryXXXXXX という名前のレポジトリが見つかるだろう (figure_title).

    ECR のコンソール画面

    次に,このレポジトリの名前をクリックするとレポジトリの詳細画面に遷移する. そうしたら,画面右上にある View push commands というボタンをクリックする. すると figure_title のようなポップアップ画面が立ち上がる.

    ECR への push コマンド

    このポップアップ画面で表示されている四つのコマンドを順番に実行していくことで,手元の Docker イメージを ECR に push することができる. push を実行する前に, AWS の認証情報が設定されていることを確認しよう. そのうえで,ハンズオンのソースコードの中にある docker/ という名前のディレクトリに移動する. そうしたら,ポップアップ画面で表示されたコマンドを上から順に実行していく.

    ポップアップで表示されるコマンドの 2 つめを見てみると docker build -t XXXXX . となっている. 最後の . が重要で,これは 現在のディレクトリにある Dockerfile を使ってイメージをビルドせよ という意味である. このような理由で, Dockerfile が置いてあるディレクトリに移動する必要がある.

    四つ目のコマンドは,数 GB あるイメージを ECR にアップロードするので少し時間がかかるかもしれないが,これが完了するとめでたくイメージが ECR に配置されたことになる. もう一度 ECR のコンソールを見てみると,確かにイメージが配置されていることが確認できる (figure_title). これで,AWS Batch を使ってジョブを実行させるための最後の準備が完了した.

    ECR へ image の配置が完了した

    単一のジョブを実行する

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    sh
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    python
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    -
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    -
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    python
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    python
    # [4]
    -submit_job(0.01, 0.1, 100)
    # [4]
    -submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは AWS CLI のインストール), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    AWS Batch でジョブが実行されている様子

    figure_title で赤で囲った箇所に注目してほしい. 一つのジョブが投入されると,それは SUBMITTED という状態を経て RUNNABLE という状態に遷移する. RUNNABLE とは, ジョブを実行するためのインスタンスが Compute environment に不足しているため,新たなインスタンスが起動されるのを待っている状態に相当する. インスタンスの準備が整うと,ジョブの状態は STARTING を経て RUNNING に至る.

    次に,ジョブのステータスが RUNNING のときの Compute environment の Desired vCPU を見てみよう (figure_title で紫で囲った箇所). ここで 4 と表示されているのは, g4dn.xlarge インスタンス一つ分の vCPU の数である. ジョブの投入に応じて,それを実行するのに最低限必要な EC2 インスタンスが起動されたことが確認できる (興味のある人は, EC2 コンソールも同時に覗いてみるとよい).

    しばらく経つと,ジョブの状態は RUNNING から SUCCEEDED (あるいは何らかの理由でエラーが発生したときには FAILED) に遷移する. 今回のハンズオンで使っている MNIST の学習はだいたい 10 分くらいで完了するはずである. ジョブの状態が SUCCEEDED になるまで見届けよう.

    ジョブが完了すると,学習の結果 (エポックごとの Loss と Accuracy を記録した CSV ファイル) は S3 に保存される. AWS コンソールからこれを確認しよう.

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    python
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    python
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    -
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    -
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    -
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    -
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    -
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    -
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    python
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    python
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    複数のジョブを同時投入したときの Job 一覧

    今度は EC2 コンソールを見てみよう. 左のメニューから Instances を選択すると, figure_title に示すような起動中のインスタンスの一覧が表示される. g4dn.xlarge が 9 台稼働しているのが確認できる. Batch がジョブの投下に合わせて必要な数のインスタンスを起動してくれたのだ!

    複数のジョブを同時投入したときの EC2 インスタンスの一覧

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    python
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    -
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    -
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    -
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    -
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    -
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    -
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    今回のパラメータサーチは勉強用に極めて単純化されたものである点は承知いただきたい.

    たとえば,今回は学習率が 0.1 が最も良いとされたが,それは訓練のエポックを 100 に限定しているからかもしれない. 学習率が低いとその分訓練に必要なエポック数も多くなる. 訓練のエポック数をもっと増やせばまた違った結果が観察される可能性はある.

    また,今回は MNIST の訓練データ 60,000 枚のうち, 48,000 枚を訓練データ,残り 12,000 枚を検証データとして用いた. この分割は乱数を固定してランダムに行ったが,もしこの分割によるデータのバイアスを気にするならば, k 個の異なる学習・検証データの分割をあらかじめ用意して,複数回モデルの評価を行う (k-fold cross-validation) 方法も,より精緻なアプローチとして考えられる.

    以上のようにして, CNN を用いた MNIST 分類モデルのハイパーパラメータの最適化の一連の流れを体験した. AWS Batch を利用することで,比較的少ないプログラミングで,動的に EC2 クラスターを制御し,並列にジョブを処理するシステムが構築できた. ここまで EC2 を使いこなすことができれば,多くの問題を自力で解くことが可能になるだろう!

    スタックの削除

    これにて,本ハンズオンは終了である.最後にスタックを削除しよう. 今回のスタックを削除するにあたり,ECR に配置された Docker のイメージは手動で削除されなければならない (これをしないと, cdk destroy を実行したときにエラーになってしまう. これは CloudFormation の仕様なので従うしかない).

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, Hands-on #2: AWS でディープラーニングを実践 で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを Hands-on #3: AWS で自動質問回答ボットを走らせる を参考に構築する.

    実際,本書ではこの流れに沿って演習を進めてきた. MNIST タスクを解くモデルを,最初 Jupyter Notebook を使用して実験し,そのコードをほとんどそのまま Docker にパッケージし, AWS Batch を用いてハイパーパラメータサーチを行った. このサイクルを繰り返すことで,クラウドを最大限に活用した機械学習アプリケーションの開発を進めることができる.

    クラウドを活用した機械学習アプリケーションの開発フロー

    小括

    ここまでが,本書第二部の内容である. 第一部に引き続き盛りだくさんの内容であったが,ついてこれたであろうか?

    第二部ではまず最初に,深層学習の計算をクラウドで実行するため, GPU 搭載型の EC2 インスタンスの起動について解説した. さらに,ハンズオンでは,クラウドに起動した仮想サーバーを使って MNIST 文字認識タスクを解くニューラルネットを訓練した (Hands-on #2: AWS でディープラーニングを実践).

    また,より大規模な機械学習アプリケーションを作るための手段として, Docker と ECS によるクラスターの初歩を説明した (Docker 入門). その応用として,英語で与えられた文章問題への回答を自動で生成するボットをクラウドに展開した (Hands-on #3: AWS で自動質問回答ボットを走らせる). タスクの投入に応じて動的に計算リソースが作成・削除される様子を実際に体験できただろう.

    さらに, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する では AWS Batch を用いてニューラルネットの学習を並列に実行する方法を紹介した. ここで紹介した方法は,ミニマムであるが,計算機システムを大規模化していくためのエッセンスが網羅されている. これらのハンズオン体験から,クラウド技術を応用してどのように現実世界の問題を解いていくのか,なんとなくイメージが伝わっただろうか?

    本書の第三部では,さらにレベルアップし,サーバーレスアーキテクチャという最新のクラウドの設計手法について解説する. その応用として,ハンズオンでは簡単な SNS サービスをゼロから実装する. 引き続きクラウドの最先端の世界を楽しんでいこう!

    Web サービスの作り方

    ここからが,本書第三部の内容になる. これまでのセクションでは,仮想サーバーをクラウド上に起動し,そこで計算を走らせる方法について解説をしてきた. EC2, ECS, Fargate, Batch などを利用して,動的にスケールするクラスターを構成し,並列にタスクを実行するクラウドシステムを実装してきた. 振り返ると,これまで紹介してきた内容は,自分自身が行いたい計算をクラウドを駆使することで実現する,という用途にフォーカスしていたことに気がつくだろう. 一方で,広く一般の人々に使ってもらえるような計算サービス・データベースを提供する,というのもクラウドの重要な役割として挙げられる.

    本章から始まる第三部では,前回までとは少し方向性を変え,どのようにしてクラウド上にアプリケーションを展開し,広く一般の人に使ってもらうか,という点を講義したいと思う. これを通じて,どのようにして世の中のウェブサービスができ上がっているのかを知り,さらにどうやって自分でそのようなアプリケーションをゼロから構築するのか,という点を学んでもらう. その過程で,サーバーレスアーキテクチャという最新のクラウド設計手法を解説する.

    その前準備として,本章ではどのようにしてウェブサービスが出来上がっているのか,その背後にある技術の概要を解説する. 用語の解説が中心となるが,後のハンズオンを実装するために必須の知識であるので,理解して前に進むよう心がけよう.

    ウェブサービスの仕組み  — Twitter を例に

    あなたがパソコンやスマートフォンから Twitter, Facebook, YouTube などのウェブサービスにアクセスしたとき,実際にどのようなことが行われ,コンテンツが提示されているのだろうか?

    HTTP を通じたサーバーとクライアントのデータのやり取りは,すでに知っている読者も多いだろうし,逆にすべて解説しようとすると紙面が足りないので,ここではエッセンスの説明のみにとどめる. 以降では Twitter を具体例として,背後にあるサーバーとクライアントの間の通信を概説しよう. 概念図としては figure_title のような通信がクライアントとサーバーの間で行われていることになる.

    クライアントと Web サーバーの通信の概念図

    前提として,クライアントとサーバーの通信は HTTP (Hypertext Transfer Protocol) を使って行われる. また,最近では,暗号化された HTTP である HTTPS (HTTPS (Hypertext Transfer Protocol Secure)) を用いることがスタンダードになってきている. 第一のステップとして,クライアントは HTTP(S) 通信によってサーバーから静的なコンテンツを取得する. 静的なコンテンツとは, HTML (Hyptertext Markup Language) で記述されたウェブページの文書本体, CSS (Cascading Style Sheets) で記述されたページのデザインやレイアウトファイル,そして JavaScript (JS) で記述されたページの動的な挙動を定義したプログラム,が含まれる. Twitter を含む現代的なウェブアプリケーションの設計では,この静的なファイル群はページの”枠”を定義するだけで,中身となるコンテンツ (例: ツイートの一覧) は別途 API (Application Programming Interface) によって取得されなければならない. そこで,クライアントは先のステップで取得された JavaScript で定義されたプログラムに従って,サーバーに API を送信し,ツイートや画像データを取得する. この際,テキストデータのやり取りには JSON (JavaScript Object Notation) というフォーマットが用いられることが多い. 画像や動画などのコンテンツも同様に API により取得される. このようにして取得されたテキストや画像が,HTML の文書に埋め込まれることで,最終的にユーザーに提示されるページが完成するのである. また,新しいツイートを投稿するときにも,クライアントから API を通じてサーバーのデータベースにデータが書き込まれる.

    REST API

    API (Application Programming Interface) とはこれまで何度も出てきた言葉であるが,ここではよりフォーマルな定義付けを行う. API とはあるソフトウェア・アプリケーションが,外部のソフトウェアに対してコマンドやデータをやり取りするための媒介の一般的総称である. とくに,ウェブサービスの文脈では,サーバーが外界に対して提示しているコマンドの一覧のことを意味する. クライアントは,提示されている API から適切なコマンドを使うことによって,所望のデータを取得したり,あるいはサーバーにデータを送信したりする.

    とくに,ウェブの文脈では REST (Representational State Transfer) とよばれる設計思想に基づいた API が現在では最も一般的に使われている. REST の設計指針に従った API のことを REST API あるいは RESTful API とよんだりする.

    REST API は, figure_title に示したような MethodURI (Universal Resource Identifier) の組からなる.

    REST API

    Method (メソッド) とは,どのような操作を行いたいかを抽象的に表す,"動詞" として捉えることができる. メソッドには HTTP 規格で定義された 9 個の動詞 (verb) を使用することができる. この中でも, GET, POST, PUT, PATCH, DELETE の 5 個が最も頻繁に使用される (table_title). この 5 つのメソッドによる操作を総称して CRUD (create, read, update, and delete) とよぶ.

    REST API Methods
    メソッド意図される動作

    GET

    要素を取得する

    POST

    新しい要素を作成する

    PUT

    既存の要素を新しい要素と置き換える

    PATCH

    既存の要素の一部を更新する

    DELETE

    要素を削除する

    一方, URI は操作が行われる対象,すなわち "目的語" を表す. ウェブの文脈では操作が行われる対象のことをしばしば リソース とよぶ. URI は多くの場合 http または https から始まるウェブサーバーのアドレスから始まり, / (スラッシュ) 以降に所望のリソースのパスが指定される. figure_title の例で言えば, https://api.twitter.com というアドレスの /1.1/status/home_timeline というリソースを取得 (GET) せよ,という意味になる (なお,ここで 1.1 という数字は API のバージョンを示している). この API リクエストによって,ユーザーのホームのタイムラインのツイートの一覧が取得される.

    REST API のメソッドには, table_title で挙げたもの以外に, HTTP プロトコルで定義されているほかのメソッド (OPTIONS, TRACE など) を用いることもできるが,あまり一般的ではない.

    また,これらのメソッドだけでは動詞として表現しきれないこともあるが, URI の名前でより意味を明確にすることもある. メソッドの使い方も,要素を削除する際は必ず DELETE を使わなければならない,という決まりもなく,たとえば, Twitter API でツイートを消す API は POST statuses/destroy/:id で定義されている. 最終的には,各ウェブサービスが公開している API ドキュメンテーションを読んで,それぞれの API がどんな操作をするのかを調べる必要がある.

    REST の概念は 2000 年代初頭に確立され,今日の API 設計のスタンダードとなった. 一方で,ウェブのテクノロジーが進歩するにつれて,新たな API の設計アプローチの需要も高まっている. 近年とくに人気を集めているのが, GraphQL と呼ばれる API の設計方法である. GraphQL は Facebook 社によって最初に作られ,現在は GraghQL Foundation によって維持と更新がされている. GraphQL を使用すると,クライアントは REST と比較してより柔軟性の高いデータのクエリを行うことができるなど,いくつかの利点がある. キーワードだけでも知っておくと,今後役に立つだろう.

    Twitter API

    もう少し具体的にウェブサービスの API を体験する目的で,ここでは Twitter の API を見てみよう. Twitter が提供している API の一覧は Twitter の Developer Documentation で見ることができる. いくつかの代表的な API を table_title にまとめた.

    Twitter API
    エンドポイント動作

    GET statuses/home_timeline

    ホームのタイムラインのツイートの一覧を取得する.

    GET statuses/show/:id

    :id で指定されたツイートの詳細情報を取得する.

    GET search

    ツイートの検索を実行する.

    POST statuses/update

    新しいツイートを投稿する.

    POST media/upload

    画像をアップロードする

    POST statuses/destroy/:id

    :id で指定されたツイートを削除する.

    POST statuses/retweet/:id

    :id で指定されたツイートをリツイートする.

    POST statuses/unretweet/:id

    :id で指定されたツイートのリツイートを取り消す.

    POST favorites/create

    選択したツイートを"いいね"する.

    POST favorites/destroy

    選択したツイートを"いいね"を取り消す.

    この API リストをもとに, Twitter のアプリまたはウェブサイトを開いたときに起こるクライアントとサーバーの通信をシミュレートしてみよう.

    ユーザーが Twitter を開くと,まず最初に GET statuses/home_timeline の API リクエストによって,ユーザーのホームのタイムラインのツイートのリストが取得される. 個々のツイートは JSON 形式のデータになっており, id, text, user, coordinates, entities などの属性を含む. id はツイートに固有な ID を表し, text はツイートの本文を含んでいる. user はツイートを投稿したユーザーの名前やプロフィール画像の URL などを含んだ JSON データになっている. coordinates にはツイートが発信された地理的な座標が記録されている. また, entities にはツイートに関連するメディアファイル (画像など) のリンクなどの情報が埋め込まれている. GET statuses/home_timeline からは直近のツイートのリスト (リストが長すぎる場合は途中で切られたもの) が取得される. もしツイートの ID を知っている場合は GET statuses/show/:id を呼ぶことによって, :id パラメータで指定された特定のツイートを取得することができる.

    ツイートの検索を行うためには GET search API を使用する. この API には,ツイートに含まれる単語や,ハッシュタグ,ツイートの発信された日時や場所など,様々なクエリの条件を渡すことができる. API からは, GET statuses/home_timeline などと同様, JSON 形式のツイートのデータが返される.

    ユーザーが新しいツイートを投稿するには POST statuses/update のエンドポイントを利用する. POST statuses/update には,ツイートの文章や,リプライの場合はリプライ先のツイートの ID などのデータを送信する. また,ツイートに画像データを添付したい場合は, POST media/upload を併せて使用する. ツイートの削除を行うには, POST statuses/destroy/:id を用いる.

    そのほか,頻繁に行われる操作としては, POST statuses/retweet/:idPOST statuses/unretweet/:id がある. これらは, :id で指定されるツイートに対して,それぞれリツイートを実行あるいは取り消すための API である. また, POST favorites/createPOST favorites/destroy を使用することによって,選択されたツイートに"いいね"を追加したり,取り消したりする操作を行う.

    このような一連の操作が, Twitter のアプリの背後では行われている. また,自分自身でボットを作成したい場合は,これらの API を適切に組み合わせ,カスタムのプログラムを書くことで実現される.

    このように, API はあらゆるウェブサービスを作るうえで一番基礎となる要素である. 次からの章では本章で紹介した用語が何度も出てくるので,頭の片隅に置いたうえで読み進めていただきたい.

    Serverless architecture

    サーバーレスアーキテクチャ (Serverless architecture) あるいは サーバーレスコンピューティング (Serverless computing) とは,従来とは全く異なるアプローチに基づくクラウドシステムの設計方法である. 歴史的には, AWS が 2014 年に発表した Lamba がサーバーレスアーキテクチャの先駆けとされている. その後, Google や Microsoft などのクラウドプラットフォームも同様の機能の提供を開始している. サーバーレスアーキテクチャの利点は,スケーラブルなクラウドシステムを安価かつ簡易に作成できる点であり,近年いたるところで導入が進んでいる.

    Serverless とは,文字どおりの意味としてはサーバーなしで計算をするということになるが,それは一体どういう意味だろうか? サーバーレスについて説明するためには,まずは従来的な, "serverful" とよばれるようなシステムについて解説しなければならない.

    Serverful クラウド (従来型)

    従来的なクラウドシステムのスケッチを figure_title に示す. クライアントから送信されたリクエストは,最初に API サーバーに送られる. API サーバーでは,リクエストの内容に応じてタスクが実行される. タスクには,API サーバーだけで完結できるものもあるが,多くの場合,データベースの読み書きが必要である. データベースには,データベース専用の独立したサーバーマシンが用いられることが一般的である. また,画像や動画などの容量の大きいデータは,また別のストレージサーバーに保存されることが多い. これらの API サーバー,データベースサーバー,ストレージサーバーはそれぞれ独立したサーバーマシンであり, AWS の言葉では EC2 による仮想インスタンスを想定してもらったらよい.

    多くのウェブサービスでは,多数のクライアントからのリクエストを処理するため,複数のサーバーマシンがクラウド内で起動し,負荷を分散するような設計がなされている. クライアントから来たリクエストを計算容量に余裕のあるサーバーに振り分けるような操作を Load balancing とよび,そのような操作を担当するマシンのことを Load balancer という.

    計算負荷を分散する目的で多数のインスタンスを起動するのはよいのだが,計算負荷が小さすぎてアイドリング状態にあるようではコストと電力の無駄遣いである. したがって,すべてのサーバーが常に目標とする計算負荷を維持するよう,計算の負荷に応じてクラスター内の仮想サーバーの数を動的に増減させるような仕組みが必要である. そのような仕組みをクラスターのスケーリングとよび,負荷の増大に応答して新しい仮想インスタンスをクラスターに追加する操作を scale-out,負荷の減少に応答してインスタンスをシャットダウンする操作を scale-in とよぶ. クラスターのスケーリングは, API サーバーではもちろんのこと,データベースサーバー・ストレージサーバーでも必要になる. ストレージサーバーでは,例えば頻繁にアクセスされるデータはキャッシュ領域に保存したり,データのコピーを複数作るなどのスケーリングが行われる. データベースサーバーも同様に,頻繁にアクセスされるデータのアクセスがパンクしてしまわないよう,分散的な処理が必要となる. このように,クラウドシステム内すべての箇所で,負荷が均一になるような調整が必要であり,開発者は多くの時間をそのチューニングに費やさなければならない. また,サービスの利用者の数などに応じてスケーリングの設定は常に見直される必要があり,継続的な開発が要求される.

    さらに問題を複雑にするのは,API サーバーで処理されるべきタスクが,非一様な点である. 非一様であるとは,たとえばタスク A は 3000 ミリ秒の実行時間と 512MB のメモリーを消費し,別のタスク B は 1000 ミリ秒の実行時間と 128MB のメモリーを消費する,というような状況を指している. 一つのサーバーマシンが計算負荷が異なる複数のタスクを処理する場合,クラスターのスケーリングはより複雑になる. この状況をシンプルにするために,1サーバーで実行するタスクは1種類に限る,という設計も可能であるが,そうするとで生まれる弊害も多い (ほとんど使われないタスクに対してもサーバー一台をまるまる割り当てなければならない = ほとんどアイドリング状態になってしまう,など).

    Serverful なクラウドシステム

    Serverless クラウドへ

    Serverful クラウド (従来型) で議論したように,クラスターのスケーリングはクラウドシステムの経済的効率とシステムの安定性を最大化するために必須の作業である. それを反映して,多くの開発者の時間が投資されてきた.

    クラスターのスケーリングはすべての開発者が何度も繰り返し行ってきた作業であり,いくつかの側面をテンプレート化し,共通化することができたならば開発のコストを大幅に削減できるだろう. それを実現するには,根本的なレベルからクラウドシステムの設計を考え直す必要がある. スケーリングを前提として考えることで,もっとシンプルで見通しがよいクラウドシステムの設計の仕組みはないだろうか? そのような動機が,サーバーレスアーキテクチャが誕生する背後にあった.

    従来の serverful なシステムでの最大の問題点は,サーバーをまるまる占有してしまうという点にある. すなわち, EC2 インスタンスを起動したとき,そのインスタンスは起動したユーザーだけが使えるものであり,計算のリソース (CPU や RAM) が独占的に割り当てられた状態になる. 固定した計算資源の割り当てがされてしまっているので,インスタンスの計算負荷が 0%であろうが 100%であろうが,均一の使用料金が起動時間に比例して発生する.

    サーバーレスアーキテクチャは,このような 独占的に割り当てられた計算リソースというものを完全に廃止することを出発点とする. サーバーレスアーキテクチャでは,計算のリソースは,クラウドプロバイダーがすべて管理する. クライアントは,仮想インスタンスを一台まるごと借りるのではなく,計算のタスクの需要が生まれる毎に,実行したいプログラム・コマンドをクラウドに提出する. クラウドプロバイダーは,自身のもつ巨大な計算リソースから空きを探し,提出されたプログラムを実行し,実行結果をクライアントに返す. 言い換えると,計算リソースのスケーリングやアロケーションなどはクラウドプロバイダーが一手に引き受け,ユーザーはジョブをサブミットすることに注力する,という枠組みである. これを図示すると, figure_title のようになる.

    従来のクラウドと Serverless クラウドの比較

    サーバーレスクラウドでは,スケーリングはすべてクラウドプロバイダーが引き受けるので,スケーラビリティーが保証されている. クライアントが同時に大量のタスクを送信した場合でも,クラウドプロバイダー側の独自の仕組みによってすべてのタスクが遅延なく実行される. また,サーバーレスクラウドを利用することで,クラウドのコストは実際に使用した計算の総量 (稼働時間) で決定されることになる. これは,計算の実行総量に関わらずインスタンスの起動時間で料金が決定されていた従来のシステムと比べて大きな違いである.

    サーバーレスクラウドは,従来のクラウドとは根本から異なったアプローチなので,コードの書き方やシステムの設計が大きく異なる. サーバーレスクラウドを開発・運用するには,サーバーレス固有の概念や用語に精通している必要がある. 以降では,実際にクラウドを動かしながら,サーバーレスをより具体的に体験していこう.

    従来型の(仮想インスタンスをたくさん起動するような)クラウドシステムは,賃貸と似ているかもしれない. 部屋を借りるというのは,その部屋でどれだけの時間を過ごそうが,月々の家賃は一定である. 同様に,仮想サーバーも,それがどれほどの計算を行っているかに関わらず,一定の料金が時間ごとに発生する.

    一方で,サーバーレスクラウドは,電気・水道・ガス料金 と似ている. こちらは,実際に使用した量に比例して料金が決定されている. サーバーレスクラウドも,実際に計算を行った総時間で料金が決まる仕組みになっている.

    サーバーレスクラウドを構成するコンポーネント

    サーバーレスアーキテクチャの概要がわかってきたところで,ここでは AWS においてサーバーレスクラウドを構成する様々なコンポーネントを紹介していこう. 特に, Lambda, S3, DynamoDB を取り上げ,解説する (figure_title). サーバーレスクラウドは,これらのコンポーネントを統合することで一つのシステムが出来上がる. ここでは, Lambda,S3,DynamoDB を利用する際に押さえておかなければならない知識を一通り説明しきる都合上,具体的なイメージがわきにくいかもしれない. が,続く Hands-on #5: サーバーレス入門 でそれぞれについてハンズオン形式で演習を行うので,そこでさらに理解を深めれば大丈夫である.

    Lambda, S3, DynamoDB のアイコン

    Lambda

    AWS でサーバーレスコンピューティングの中心を担うのが, Lambda である. Lambda の使い方を figure_title に図示している. Lambda の仕組みはシンプルで,まずユーザーは実行したいプログラムのコードを事前に登録しておく. プログラムは, Python, Node.js, Ruby などの主要な言語がサポートされている. Lambda に登録されたひとつひとつのプログラムを関数 (Function) とよぶ. そして,関数を実行したいときに,invoke コマンドを Lambda に送信する. Lambda では, invoke のリクエストを受け取るとただちに (数ミリセカンドから数百ミリセカンド程度の時間で) プログラムの実行を開始する. そして,実行結果をクライアントやその他の計算機に返す.

    AWS Lambda

    このように,Lambda では占有された仮想インスタンスは存在せず,実行を待っているプログラムだけがある状態である. invoke のリクエストに応じて,プログラムが AWS の巨大な計算機プールのどこかに配置され,実行される. 同時に複数のリクエストが来た場合でも, AWS はそれらを実行するための計算リソースを割り当て,並列的に処理を行ってくれる. 原理上は,数千から数万のリクエストが同時に来たとしても, Lambda はそれらを同時に実行することができる. このような,占有された仮想サーバーの存在なしに,動的に関数を実行するサービスのことを総称して FaaS (Function as a Service) とよぶ.

    Lambda ではそれぞれの関数につき, 128MB から 10240MB のメモリーを使用することができる (執筆時点の仕様). また,実効的な CPU のパワーはメモリーの量に比例する形で割り当てられる. すなわち,タスクに割り当てたメモリーの量が多ければ多いほど,より多くの CPU リソースが割り当てられることになる (しかし, RAM と CPU パワーの具体的な換算表は AWS からは公開されていない). 実行時間は 100 ミリ秒の単位で記録され,実行時間に比例して料金が決定される. table_title は Lambda の利用料金表である (執筆時点で ap-north-east1 リージョンを選択した場合).

    Lambda の料金表
    Memory (MB)Price per 100ms

    128

    $0.0000002083

    512

    $0.0000008333

    1024

    $0.0000016667

    3008

    $0.0000048958

    実行時間に比例する料金に追加して,リクエストを送信するごとに発生する料金が設定されている. これは,百万回のリクエストにつき $0.2 である. たとえば, 128MB のメモリーを使用する関数を,それぞれ 200 ミリ秒,合計で 100 万回実行した場合, 0.0000002083 * 2 * 10^6 + 0.2 = $0.6 の料金となる. ウェブサーバーのデータベースの更新など簡単な計算であれば,200 ミリ秒程度で実行できる関数も多いことから,100 万回データベースの更新を行ったとしても,たった $0.6 しかコストが発生しないことになる. また,コードが実行されず待機状態になっている場合は,発生する料金は 0 である. このように,実際に意味のある処理が行われた時間にのみ,料金が発生する仕組みになっている.

    Lambda は比較的短時間で完了する,反復性の高いタスクの実行に向いている. データベースの読み書きはその典型的な例であるが,そのほかにも,画像のサイズをトリミングしたり,サーバーサイドで定期的に実行されるメンテナンス処理などの利用が考えられる. また,複数の Lambda をリレー式に繋げることも可能で,シンプルな処理を組み合わせることで複雑なロジックを表現することができる.

    上述の Lambda の料金計算は,説明のためコストに寄与する要素をいくつか省いている点は承知いただきたい. 例えば, DynamoDB の読み書きに関する料金や,ネットワークの通信にかかわるコストが考慮されていない.

    サーバーレスストレージ: S3

    サーバーレスの概念は,ストレージにも拡張されている.

    従来的なストレージ (ファイルシステム) では,必ずホストとなるマシンと OS が存在しなければならない. したがって,それほどパワーは必要ないまでも,ある程度の CPU リソースを割かなければならない. また,従来的なファイルシステムでは,データ領域のサイズは最初にディスクを初期化するときに決めなければならず,後から容量を増加させることはしばしば困難である (ZFS などのファイルシステムを使えばある程度は自由にファイルシステムのサイズを変更することは可能である). よって,従来的なクラウドでは,ストレージを借りる際にはあらかじめディスクのサイズを指定せねばならず,ディスクの中身が空であろうと満杯であろうと,同じ利用料金が発生することになる (figure_title).

    Simple Storage Service (S3) は,サーバーレスなストレージシステムを提供する (figure_title). S3 は従来的なストレージシステムと異なり, OS に"マウントする”という概念はない. 基本的に API を通じてデータの読み書きの操作が行われる. また,データの冗長化や暗号化,バックアップの作成など,通常ならば OS と CPU が介在しなければならない操作も, API を通じて行うことができる. S3 では事前に決められたディスク領域のサイズはなく,データを入れれば入れた分だけ,保存領域は拡大していく (仕様上はペタバイトスケールのデータを保存することが可能である). ストレージにかかる料金は,保存してあるデータの総容量で決定される.

    S3 と従来的なファイルシステムの比較

    S3 を利用する際に,料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 説明のため主要な事項のみ取り出している. 詳細は 公式ドキュメンテーション "Amazon S3 pricing" を参照).

    S3 の利用料金
    項目料金

    Data storage (First 50TB)

    $0.023 per GB per month

    PUT, COPY, POST, LIST requests (per 1,000 requests)

    $0.005

    GET, SELECT, and all other requests (per 1,000 requests)

    $0.0004

    Data Transfer IN To Amazon S3 From Internet

    $0

    Data Transfer OUT From Amazon S3 To Internet

    $0.09 per GB

    第一に,データの保存には $0.025 per GB のコストが月ごとに発生する. したがって,1000GB のデータを S3 に一ヵ月保存した場合, $25 の料金が発生することになる. また,PUT, COPY, POST などのリクエスト (=データを書き込む操作) に対しては,データ容量に関係なく,1000 回ごとに $0.005 のコストが発生する. GET, SELECT などのリクエスト (=データを読み込む操作) に対しては,1000 回ごとに $0.0004 のコストが発生する. また, S3 はデータを外に取り出す際の通信にもコストが生じる. 執筆時点では,S3 からインターネットを通じて外部にデータを転送 (data-out) すると $0.09 per GB のコストが発生する. データをインターネットを通じて S3 に入れる (data-in) 通信は無料で行える. また, AWS の 同じ Region 内のサービス (Lambda や EC2 など) にデータを転送するのは無料である. AWS のリージョンをまたいだデータの転送にはコストが発生する. いずれにせよ,サーバーレスの概念に則り,すべての料金が従量課金制で決定される設定になっている.

    サーバーレスデータベース: DynamoDB

    サーバーレスの概念は,データベースにも適用することができる.

    ここでいうデータベースとは, Web サービスなどにおけるユーザーや商品の情報を記録しておくための保存領域のことを指している. 従来的に有名なデータベースとしては MySQL, PostgreSQL, MongoDB などが挙げられる. データベースと普通のストレージの違いは,データの検索機能にある. 普通のストレージではデータは単純にディスクに書き込まれるだけだが, データベースでは検索がより効率的になるようなデータの配置がされたり, 頻繁にアクセスされるデータはメモリーにキャッシュされるなどの機能が備わっている. これにより,巨大なデータの中から,興味のある要素を高速に取得することができる.

    このような検索機能を実現するには,当然 CPU の存在が必須である. したがって,従来的なデータベースを構築する際は,ストレージ領域に加えて,たくさんの CPU コアを搭載したマシンが用いられることが多い. また,データベースが巨大な場合は複数マシンにまたがった分散型のシステムが設計される. 分散型システムの場合は, Serverful クラウド (従来型) で議論したようにデータベースへのアクセス負荷に応じて適切なスケーリングがなされる必要がある.

    DynamoDB は, AWS が提供しているサーバーレスな分散型データベースである. サーバーレスであるので,占有されたデータベース用仮想インスタンスは存在せず, API を通じてデータの書き込み・読み出し・検索などの操作を行う. S3 と同様に,データ保存領域の上限は定められておらず,データを入れれば入れた分だけ,保存領域は拡大していく. また,データベースへの負荷が増減したときのスケーリングは, DynamoDB が自動で行うので,ユーザーは心配する必要はない.

    DynamoDB での利用料金の計算はやや複雑なのだが, "On-demand Capacity" というモードで使用した場合の料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 詳細は 公式ドキュメンテーション "Pricing for On-Demand Capacity" を参照).

    DynamoDB の利用料金
    項目料金

    Write request units

    $1.25 per million write request units

    Read request units

    $0.25 per million read request units

    Data storage

    $0.25 per GB-month

    DynamoDB ではデータの書き込み操作の単位を write request unit とよび,データの読み込み操作の単位を read request unit とよぶ. 基本的に, 1kB 以下のデータを一度書き込むと 1 write request unit を消費し,4kB 以下のデータを一度読み込むと 1 read request unit を消費する (詳しくは 公式ドキュメンテーション "Read/Write Capacity Mode" を参照のこと). write request units は 100 万回ごとに $1.25, read request units は 100 万回ごとに $0.25 のコストが設定されている. また,保存されたデータ容量に対して $0.25 per GB のコストが月ごとに発生する. DynamoDB は高速な検索機能などを備えたデータベースであるので, GB あたりのストレージコストは S3 に比べ 10 倍程度高い. DynamoDB のデータの転送に関わるコストは,同じリージョン内ならば data-in,data-out ともに $0 である. リージョンをまたいだ通信には別途コストが発生する.

    その他のサーバーレスクラウドの構成要素

    以上で紹介した Lambda, S3, DynamoDB がサーバーレスクラウドの中で最も使用する頻度が高いサービスになる. その他のサーバーレスクラウドの構成要素を以下に列挙する. いくつかについては,今後のハンズオンを行う中で改めて解説を行う.

    サーバーレスアーキテクチャは万能か?

    この問いへの答えは,筆者は NO であると考える.

    ここまで,サーバーレスの利点を強調して説明をしてきたが,まだまだ新しい技術なだけに,欠点,あるいはサーバーフルなシステムに劣る点は数多くある.

    大きな欠点を一つあげるとすれば,サーバーレスのシステムは各クラウドプラットフォームに固有なものなので,特定のプラットフォームでしか運用できないシステムになってしまう点であろう. AWS で作成したサーバーレスのシステムを, Google のクラウドに移植するには,かなり大掛かりなプログラムの書き換えが必要になる. 一方, serverful なシステムであれば,プラットフォーム間のマイグレーションは比較的簡単に行うことができる. クラウドプロバイダーとしては,自社のシステムへの依存度を強めることで,顧客を離さないようにするという狙いがあるのだろう…

    その他,サーバーレスコンピューティングの欠点や今後の課題などは,次の論文で詳しく議論されている. 興味のある読者はぜひ読んでいただきたい.

    Hands-on #5: サーバーレス入門

    前章ではサーバーレスアーキテクチャの概要の説明を行った. 本章では,ハンズオン形式でサーバーレスクラウドを実際に動かしながら,具体的な使用方法を学んでいこう. 今回のハンズオンでは Lambda, S3, DynamoDB の三つのサーバーレスクラウドの構成要素に触れていく. それぞれについて,短いチュートリアルを用意してある.

    Lambda ハンズオン

    まずは, Lambda を実際に動かしてみよう. ハンズオンのソースコードは GitHub の handson/serverless/lambda に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して Python で書かれたコードを Lambda に登録する. 続いて STEP 2 では, Invoke API を使用して,同時にいくつもの Lambda を起動し,並列な計算を行う. Lambda のワークフローを体験する目的で最小限の設定である.

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    py
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    -
    -class SimpleLambda(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    -
    -class SimpleLambda(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

    • 次に, Lambda に <1> で書いた関数を配置している. パラメータの意味は,文字どおりの意味なので難しくはないが,以下に解説する.

      • runtime=_lambda.Runtime.PYTHON_3_7: ここでは, Python3.7 を使って上記で定義された関数を実行せよ,と指定している. Python3.7 のほかに, Node.js, Java, Ruby, Go などの言語を指定することが可能である.

      • code=_lambda.Code.from_inline(FUNC): 実行されるべき関数が書かれたコードを指定する. ここでは, FUNC=... で定義した文字列を渡しているが,文字列以外にもファイルのパスを渡すことも可能である.

      • handler="index.handler": これは,コードの中にいくつかのサブ関数が含まれているときに,メインとサブを区別するためのパラメータである. handler という名前の関数をメイン関数として実行せよ,という意味である.

      • memory_size=128: メモリーは 128MB を最大で使用することを指定している.

      • timeout=core.Duration.seconds(10) タイムアウト時間を 10 秒に設定している. 10 秒以内に関数の実行が終了しなかった場合,エラーが返される.

      • dead_letter_queue_enabled=True: アドバンストな設定なので説明は省略する.

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    Lambda コンソール - 関数の一覧

    今回のアプリケーションで作成したのが SimpleLambda で始まるランダムな名前のついた関数だ. 関数の名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. 先ほどプログラムの中で定義した Python の関数がエディターから確認できる. さらに下の方にスクロールすると,関数の各種設定も確認できる.

    Lambda コンソール - 関数の詳細

    Lambda で実行されるコードは, Lambda のコンソール画面 (figure_title) のエディターで編集することもできる. デバッグをするときなどは,こちらを直接いじる方が早い場合もある. その場合は, CDK のコードに行った編集を反映させなおすことを忘れずに.

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    sh
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    ....................................................................................................
    -Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    figure_title で "Invocations" が関数が何度実行されたかを意味している. たしかに 100 回実行されていることがわかる. さらに, "Concurrent executions" は何個のタスクが同時に行われたかを示している. ここでは 96 となっていることから,96 個のタスクが並列的に実行されたことを意味している (これが 100 とならないのは,タスクの開始のコマンドが送られたのが完全には同タイミングではないことに起因する).

    このように,非常にシンプルではあるが, Lambda を使うことで,同時並列的に処理を実行することのできるクラウドシステムを簡単に作ることができた.

    もしこのようなことを従来的な serverful なクラウドで行おうとした場合,クラスターのスケーリングなど多くのコードを書くことに加えて,いろいろなパラメータを調節する必要がある.

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • partition_key: すべての DynamoDB テーブルには Partition key が定義されていなければならない. Partition key とは,テーブル内の要素 (レコード) ごとに存在する固有の ID のことである. 同一の Partition key をもった要素がテーブルの中に二つ以上存在することはできない (注: Sort Key を使用している場合は除く.詳しくは 公式ドキュメンテーション "Core Components of Amazon DynamoDB" 参照). また, Partition key が定義されていない要素はテーブルの中に存在することはできない. ここでは, Partition key に item_id という名前をつけている.

    • billing_mode: ddb.BillingMode.PAY_PER_REQUEST を指定することで, On-demand Capacity Mode の DynamoDB が作成される. ほかに PROVISIONED というモードがあるが,これはかなり高度なケースを除いて使用しないだろう.

    • removal_policy: CloudFormation のスタックが消去されたときに, DynamoDB も一緒に消去されるかどうかを指定する. このコードでは DESTROY を選んでいるので,すべて消去される. ほかのオプションを選択すると,スタックを消去しても DynamoDB のバックアップを残す,などの動作を定義することができる.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    DynamoDB のコンソール (テーブルの一覧)

    今回のアプリケーションで作成したのが SimpleDynamoDb で始まるランダムな名前のついたテーブルだ. テーブルの名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. "Items" のタブをクリックすると,テーブルの中のレコードを確認できる. 現時点ではなにもデータを書き込んでいないので,空である.

    DynamoDB のコンソール (テーブルの詳細画面)

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    python
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    -
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    -
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    python
    import boto3
    -ddb = boto3.resource('dynamodb')
    -
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    import boto3
    -ddb = boto3.resource('dynamodb')
    -
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    python
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if key is None:
    -        key = os.path.basename(filename)
    -
    -    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if key is None:
    -        key = os.path.basename(filename)
    -
    -    bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    python
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if filename is None:
    -        filename = os.path.basename(key)
    -
    -    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if filename is None:
    -        filename = os.path.basename(key)
    -
    -    bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #6: Bashoutter

    さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

    ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

    準備

    ハンズオンのソースコードは GitHub の handson/bashoutter に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. それ以外に必要な準備はない.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行できる.

    アプリケーションの説明

    API

    今回のアプリケーションでは,人々からの俳句の投稿を受け付けたり,投稿された俳句の一覧を取得する,といった機能を実装したい. この機能を実現するための最小限の設計として, table_title に示すような四つの REST API を今回は実装する. 俳句を投稿する,閲覧する,削除するという基本的なデータ操作を行うための API が完備されている. また, PATCH /haiku/{item_id} は, {item_id} で指定された俳句に”いいね”をするために使用する.

    Bashoutter API

    GET /haiku

    俳句の一覧を取得する

    POST /haiku

    新しい俳句を投稿する

    PATCH /haiku/{item_id}

    {item_id} で指定された俳句にお気に入り票を一つ入れる

    DELETE /haiku/{item_id}

    {item_id} で指定された俳句を削除する

    それぞれの API のパラメータおよび返り値の詳細は,ハンズオンのソースコードの中の swagger.yml に定義してある.

    Open API Specification (OAS; 少し前は Swagger Specification とよばれていた) は, REST API のための記述フォーマットである. OAS に従って API の仕様が記述されていると,簡単にドキュメンテーションを生成したり,クライアントアプリケーションを自動生成することができる. 今回用意した API 仕様 も, OAS に従って書いてある. 詳しくは Swagger の公式ドキュメンテーション などを参照.

    アプリケーションアーキテクチャ

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#5で作製するアプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントからの API リクエストは, API Gateway (後述)にまず送信され, API の URI で指定された Lambda 関数へ転送される.

    • それぞれの API のパス (リソース) ごとに独立した Lambda を用意する.

    • 俳句の情報 (作者,本文,投稿日時など) を記録するためのデータベース (DynamoDB) を用意する.

    • 各 Lambda 関数には, DynamoDB へのアクセス権を付与する.

    • 最後に,ウェブブラウザからコンテンツを表示できるよう, ウェブページの静的コンテンツを配信するための S3 バケットを用意する.クライアントはこの S3 バケットにアクセスすることで HTML/CSS/JS などのコンテンツを取得する.

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    python
    class Bashoutter(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    -
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    -
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    -
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    -
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    -
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    class Bashoutter(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    -
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    -
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    -
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    -
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    -
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

    • 静的コンテンツを配信するための S3 バケットを用意している.

    • それぞれの API で実行される Lambda 関数を定義している. 関数は Python3.7 で書かれており,コードは handson/bashoutter/api/api.py にある.

    • <3> で定義された Lambda 関数に対し,データベースへの読み書きのアクセス権限を付与している.

    • ここで,API Gateway により,各 API パスとそこで実行されるべき Lambda 関数を紐付けている.

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    python
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    今回のハンズオンでは説明の簡略化のため CloudFront の設定を行わなかったが,興味のある読者は次のリンクのプログラムが参考になるだろう.

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    python
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    python
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    -
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    -
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    -
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    -
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    python
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    そのような理由により,このコードでは GET のハンドラー関数に対しては grant_read_data() によって, read 権限のみを付与している.

    API Gateway

    API Gateway とは, API の"入り口"として,API のリクエストパスに従って Lambda や EC2 などに接続を行うという機能を担う (figure_title). Lambda や EC2 によって行われた処理の結果は,再び API Gateway を経由してクライアントに返される. このように,クライアントとバックエンドサーバーの間に立ち, API のリソースパスに応じて接続先を振り分けるようなサーバーをルーター,あるいはリバースプロキシとよんだりする. 従来的には,ルーターにはそれ専用の仮想サーバーが置かれることが一般的であった. しかし, API Gateway はサーバーレスなルーターとして,固定されたサーバーを配置することなく, API のリクエストが来たときのみ起動し,API のルーティングを実行する. サーバーレスであることの当然の帰結として,アクセスの件数が増大したときにはそれにルーティングの処理能力を自動で増やす機能も備わっている.

    API Gateway

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    python
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    -
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    -
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    -
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    -
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

    • 次に, api.root.add_resource() のメソッドを呼ぶことで, /haiku という API パスを追加している.

    • 続いて, add_method() を呼ぶことで, GET, POST のメソッドを /haiku のパスに定義している.

    • さらに, haiku.add_resource("{item_id}") により, /haiku/{item_id} という API パスを追加している.

    • 最後に, add_method() を呼ぶことにより, PATCH, DELETE のメソッドを /haiku/{item_id} のパスに定義している.

    このように, API Gateway の使い方は非常にシンプルで,逐次的に API パスとそこで実行されるメソッド・Lambda を記述していくだけでよい.

    このプログラムで 新規 API を作成すると, ランダムな URL がその API のエンドポイントとして割り当てられる. これを. api.example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    API Gateway コンソール画面 (1)

    今回デプロイした "BashoutterApi" という名前の API をクリックすることで figure_title のような画面に遷移し,詳細情報を閲覧できる. GET /haiku, POST /haiku などが定義されていることが確認できる.

    それぞれのメソッドをクリックすると,そのメソッドの詳細情報を確認できる. API Gateway は,前述したルーティングの機能だけでなく,認証機能などを追加することも可能である. このハンズオンではとくにこれらの機能は使用しないが, "Method Request" と書いてある項目などがそれに相当する. 次に, figure_title で画面右端の赤色で囲った部分に,この API で呼ばれる Lambda 関数が指定されていることに注目しよう. 関数名をクリックと,該当する Lambda のコンソールに遷移し,関数の中身を閲覧することが可能である.

    API Gateway コンソール画面 (2)

    次に, S3 のコンソール画面に移ってみよう. bashouter- で始まるランダムな名前のバケットが見つかるはずである (figure_title).

    S3 コンソール画面

    バケットの名前をクリックすることで,バケットの中身を確認してみよう. index.html のほか, css/, js/ などのディレクトリがあるのが確認できるだろう (figure_title). これらが,ウェブページの"枠"を定義している静的コンテンツである.

    S3 バケットの中身

    API リクエストを送信する

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    $ http GET "\${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    sh
    $ http POST "\${ENDPOINT_URL}/haiku" \\
    -username="松尾芭蕉" \\
    -first="閑さや" \\
    -second="岩にしみ入る" \\
    -third="蝉の声"
    $ http POST "\${ENDPOINT_URL}/haiku" \\
    -username="松尾芭蕉" \\
    -first="閑さや" \\
    -second="岩にしみ入る" \\
    -third="蝉の声"

    次のような出力が得られるだろう.

    sh
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    -
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    $ http GET "\${ENDPOINT_URL}/haiku"
    -
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    sh
    $ http PATCH "\${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "\${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    sh
    $ http GET "\${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    $ http GET "\${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    sh
    $ http DELETE "\${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "\${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている (figure_title 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    ウェブブラウザを開き,アドレスバーに S3 の URL を入力しへアクセスしてみよう. すると, figure_title のようなページが表示されるはずである.

    "Bashoutter" の GUI 画面

    ページが表示されたら,一番上の "API Endpoint URL" と書いてあるテキストボックスに,今回デプロイした API Gateway の URL を入力する (今回のアプリケーションでは,API Gateway の URL はランダムに割り当てられるのでこのような GUI の仕様になっている). そうしたら,画面の "REFRESH" と書いてあるボタンを押してみよう. データベースに俳句が登録済みであれば,俳句の一覧が表示されるはずである. 各俳句の左下にあるハートのアイコンをクリックすることで, "like" の票を入れることができる.

    新しい俳句を投稿するには,五七五と投稿者の名前を入力して, "POST" を押す. "POST" を押した後は,再び "REFRESH" ボタンを押すことで最新の俳句のリストをデータベースから取得する.

    アプリケーションの削除

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. Hands-on #5: サーバーレス入門 では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    これらの演習を通じて,世の中のウェブサービスがどのようにしてでき上がっているのか,少し理解が深まっただろうか? また,そのようなウェブアプリケーションを自分が作りたいと思ったとき,今回のハンズオンがその出発点となることができたならば幸いである.

    まとめ

    Appendix: 環境構築

    本書を読み進めるにあたって,ハンズオンのプログラムを実行するための環境を自分のローカルマシンにセットアップしなければならない. ここでは, AWS やコマンドラインの初心者を想定して,本章で必要なソフトウェアやライブラリのインストールなどを簡単に解説する. 以下に簡単な目次を示そう. 既に環境構築が済んでいる場合は適宜読み飛ばしていただき,関係のある箇所のみ目を通せば良い.

    使用する OS は Linux/Mac/Windows のどれを用いても構わない. Windows のユーザーは, Windows Subsytem for Linux (WSL) を使用することを想定している (WSL のインストール).

    また,本書のハンズオンを実行するための Docker イメージ を提供している. これを用いると, AWS CLI/CDK や Python の設定などをスキップできるので, Docker の使用方法を知っている読者には便利だろう.

    AWS アカウントの取得

    本書で提供するハンズオンを実際に自分で試すには,読者自身で AWS のアカウントの作成をする必要がある. 詳しいアカウントの作成の手順は 公式のドキュメンテーション に書かれているので,そちらも参照していただきたい. 以下の手順に従ってアカウントの作成を行う.

    まず,ウェブブラウザから AWS コンソール にアクセスし,右上の Create an AWS Account をクリックする (figure_title で実線で囲った部分).

    サインアップ (1): AWS コンソールにアクセス

    次に,遷移した先のページでメールアドレスとパスワードなどの登録を行う (figure_title).

    サインアップ (2): メールアドレス・パスワードなどの登録.

    続いて,住所や電話番号などを訊かれるので,すべて入力しよう (figure_title).

    サインアップ (3): 住所・電話番号の入力

    次に,クレジットカードの情報の登録を求められる (figure_title). 個人で AWS を利用する場合は,利用料金の請求はクレジットカードを経由して行われる. クレジットカードの登録なしには AWS を使い始めることはできないことに注意.

    サインアップ (4): クレジットカードの登録

    次の画面では,携帯電話の SMS またはボイスメッセージを利用した本人確認が求められる (figure_title). 希望の認証方法を選択し,自分の携帯電話番号を入力しよう.

    サインアップ (5): 携帯電話による本人確認

    無事に本人確認が完了すると,最後にサポートプランの選択を求められる (figure_title). 無料の Basic support を選択しておけば問題ない.

    サインアップ (6): サポートプランの選択

    以上のステップにより,アカウントの作成が完了する (figure_title). 早速ログインをして, AWS コンソールにアクセスできるか確認しておこう.

    サインアップ (7): アカウントの作成が完了した

    AWS のシークレットキーの作成

    AWS シークレットキーとは, AWS CLI や AWS CDK から AWS の API を操作するときに,ユーザー認証を行うための鍵のことである. AWS CLI/CDK を使うには,最初にシークレットキーを発行する必要がある. AWS シークレットキーの詳細は 公式ドキュメンテーション "Understanding and getting your AWS credentials" を参照.

    1. AWS コンソールにログインする.

    2. 画面右上のアカウント名をクリックし,表示されるプルダウンメニューから "My Security Credentials" を選択 (figure_title)

    3. "Access keys for CLI, SDK, & API access" の下にある "Create accesss key" のボタンをクリックする (figure_title)

    4. 表示された Access key ID, Secret access key を記録しておく (画面を閉じると二度と表示されない).

    5. 鍵を忘れてしまった場合などは,同じ手順で再発行が可能である.

    6. 発行したシークレットキーは, ~/.aws/credentials のファイルに書き込むか,環境変数に設定するなどして使う (詳しくは AWS CLI のインストール).

    AWS シークレットキーの発行1

    AWS シークレットキーの発行2

    AWS Educate Starter Account を用いている場合は,次の手順でシークレットキーを確認する.

    • AWS Educate のコンソール画面から, vocareum のコンソールに移動する (figure_title).

    • Account Details をクリックし,続いて AWS CLI: Show をクリックする.

    • aws_access_key_id, aws_secret_access_key, aws_session_token が表示される (figure_title). ここで表示された内容を ~/.aws/credentials にコピーする (AWS CLI のインストール 参照). aws_session_token の箇所も漏らさずコピーすること.

    • 続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

      [default] region = us-east-1 output = json

    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).

    vocareum コンソール

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    sh
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    -
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    -
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    本書のハンズオンではコマンドラインから AWS CLI のコマンドを実行したり, Python で書かれたプログラムを実行する. コマンドは基本的に UNIX のターミナルを想定して書かれている. Linux や Mac のユーザーは OS に標準搭載されているターミナルを用いれば良い. Windows を利用している読者は, Windows Subsystem for Linux (WSL) を利用することで,仮想の Linux 環境を構築することを推奨する. Cygwin などの Linux 環境をエミュレートするほかのツールでも構わないが,本書のプログラムは WSL でのみ動作確認を行っている.

    WSL とは, Windows の OS 上で Linux の仮想環境を起動するための, Microsoft 社が公式で提供しているソフトウェアである. Ubuntu など希望の Linux distribution が選択でき,基本的にすべての Linux 向けに作られたプログラム・ソフトウェアを使用することができる.

    執筆時点では WSL 2 が最新版として提供されているので,以下では WSL 2 のインストール手順を簡単に説明する. 細かな詳細などは, 公式ドキュメンテーション を参照のこと.

    前提として,使用される OS は Windows 10 (Pro または Home エディション) でなければならない. さらに,使用している Windows 10 のバージョンが WSL に対応するバージョンであるかを確認する. X64 のシステムでは Version 1903, Build 18362 以上でなければならない. バージョンが対応していない場合は、 Windows のアップデートを行う.

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    powersh
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    sh
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    Ubuntu 20.04 を初回に起動すると,初期設定が自動で開始され,数分待つことになる. 初期設定が終わると,ユーザー名・パスワードを設定するようプロンプトが出るので,プロンプトに従い入力する.

    これで WSL2 のインストールが完了した. 早速 WSL2 を起動してみよう. 左下の Windows メニューの検索バーに Ubuntu と入力すると, Ubuntu 20.04 のプログラムが見つかるはずである (figure_title). クリックして起動しよう.

    Ubuntu 20.04 の起動

    すると,ターミナルの黒い画面が立ち上がるだろう (figure_title). ls, top などのコマンドを打ってみて, WSL がきちんと動作していることを確認しよう.

    WSL の起動画面

    オプションとして, Windows Terminal というマイクロソフトから提供されているツールを使うと,より快適に WSL を使用することができる. 興味のある読者はこちらのインストールも推奨する.

    Docker のインストール

    Docker のインストールの方法は OS によって異なる.

    Mac ユーザーは, Docker Desktop をインストールする. インストールの方法は, Docker のウェブサイト から, Mac 版の Docker Desktop をダウンロードし,ダウンロードされたファイルをダブルクリックし, Applications のフォルダにドラッグするだけで良い. 詳細は 公式ドキュメンテーション を参照のこと.

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh\n$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh\n$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    ハンズオンを実行するために必要な, Node.js, Python, AWS CDK などがインストールされた Docker image を用意した. これを使用することで,自分のローカルマシンに諸々をインストールする必要なく,すぐにハンズオンのコードが実行できる.

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    sh
    root@aws-handson:~/programlisting
    root@aws-handson:~/programlisting

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい (プログラムを実行する など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    ライセンス

    本教科書およびハンズオンのソースコードは CC BY-NC-ND 4.0 に従うライセンスで公開しています.

    教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.

    ',1318);function za(xa,Ta,Wa,$a,La,Ga){const p=l;return qa(),Da("div",null,[Ea,Ca(p,{readTime:"141",words:"34.3k"}),Ia])}const ln=va(Pa,[["render",za]]);export{pn as __pageData,ln as default}; diff --git a/assets/development_aws_main.md.58c079df.lean.js b/assets/development_aws_main.md.58c079df.lean.js deleted file mode 100644 index f612d235..00000000 --- a/assets/development_aws_main.md.58c079df.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as l}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o}from"./chunks/earth_from_earth.8c108f53.js";import{_ as e,a as t,b as r,c}from"./chunks/terminal.94539704.js";import{_ as i,a as y,b as d,c as u,d as b,e as m,f as A,g as h,h as B,i as g,j as _}from"./chunks/iac.2263bc12.js";import{_ as s,a}from"./chunks/VPC.e1acca4d.js";import{_ as f,a as k,b as v,c as q,d as D,e as C,f as S}from"./chunks/ec2_keypair_console.fc89ef69.js";import{_ as w,a as P}from"./chunks/cnn.a8836fd9.js";import{_ as E,a as I,b as z,c as x,d as T,e as W,f as $,g as L,h as G,i as N,j as U,k as R,l as X,m as M,n as H,o as F,p as O}from"./chunks/mnist_prediction.4ba5b405.js";import{_ as j,a as V,b as K,c as Y,d as J,e as Q,f as Z,g as ss}from"./chunks/ecs.73d77e6a.js";import{_ as as,a as ns,b as ps,c as ls,d as os,e as es,f as ts,g as rs,h as cs,i as is,j as ys}from"./chunks/ask_many_output.0bb19110.js";import{_ as ds,a as us,b as bs,c as ms,d as As,e as hs,f as Bs,g as gs,h as _s,i as fs,j as ks,k as vs,l as qs,m as Ds,n as Cs,o as Ss,p as ws,q as Ps,r as Es,s as Is}from"./chunks/cloud_development.e43e5d4a.js";import{_ as zs,a as xs}from"./chunks/rest_api.602a6e96.js";import{_ as Ts,a as Ws,b as $s,c as Ls,d as Gs}from"./chunks/s3_vs_filesystem.fd65005d.js";import{_ as Ns,a as Us,b as Rs,c as Xs,d as Ms,e as Hs,f as Fs,g as Os,h as js,i as Vs,j as Ks,k as Ys,l as Js}from"./chunks/s3_bucket_filelist.89f3f384.js";import{_ as Qs,a as Zs,b as sa,c as aa,d as na,e as pa,f as la,g as oa,h as ea}from"./chunks/bashoutter_2.cd8a2a95.js";import{_ as ta,a as ra,b as ca,c as ia,d as ya,e as da,f as ua,g as ba,h as ma,i as Aa,j as ha,k as Ba,l as ga,m as _a,n as fa,o as ka}from"./chunks/venv_shell.dc2530bc.js";import{_ as va,o as qa,c as Da,H as Ca,k as n,a as Sa,Q as wa}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const pn=JSON.parse('{"title":"はじめに!","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/main.md","filePath":"development/aws/main.md","lastUpdated":1695377563000}'),Pa={name:"development/aws/main.md"},Ea=n("h1",{id:"はじめに",tabindex:"-1"},[Sa("はじめに! "),n("a",{class:"header-anchor",href:"#はじめに","aria-label":'Permalink to "はじめに!"'},"​")],-1),Ia=wa("",1318);function za(xa,Ta,Wa,$a,La,Ga){const p=l;return qa(),Da("div",null,[Ea,Ca(p,{readTime:"141",words:"34.3k"}),Ia])}const ln=va(Pa,[["render",za]]);export{pn as __pageData,ln as default}; diff --git a/assets/development_aws_scientific-computing.md.1b192c5b.js b/assets/development_aws_scientific-computing.md.194874e2.js similarity index 99% rename from assets/development_aws_scientific-computing.md.1b192c5b.js rename to assets/development_aws_scientific-computing.md.194874e2.js index 74ee87ae..ca3e7925 100644 --- a/assets/development_aws_scientific-computing.md.1b192c5b.js +++ b/assets/development_aws_scientific-computing.md.194874e2.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as r}from"./chunks/cnn.a8836fd9.js";import{_ as o,o as d,c as n,H as i,k as t,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"クラウドで行う科学計算・機械学習","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/scientific-computing.md","filePath":"development/aws/scientific-computing.md","lastUpdated":1695377563000}'),c={name:"development/aws/scientific-computing.md"},h=t("h1",{id:"クラウドで行う科学計算・機械学習",tabindex:"-1"},[s("クラウドで行う科学計算・機械学習 "),t("a",{class:"header-anchor",href:"#クラウドで行う科学計算・機械学習","aria-label":'Permalink to "クラウドで行う科学計算・機械学習"'},"​")],-1),P=l('

    計算機が発達した現代では,計算機によるシミュレーションやビッグデータの解析は,科学・エンジニアリングの研究の主要な柱である. これらの大規模な計算を実行するには,クラウドは最適である. 本章から始まる第二部では,どのようにしてクラウド上で科学計算を実行するのかを,ハンズオンとともに体験してもらう. 科学計算の具体的な題材として,今回は機械学習(深層学習)を取り上げる.

    なお,本書では PyTorch ライブラリを使って深層学習のアルゴリズムを実装するが,深層学習および PyTorch の知識は不要である. 講義ではなぜ・どうやって深層学習をクラウドで実行するかに主眼を置いているので,実行するプログラムの詳細には立ち入らない. 将来,自分で深層学習を使う機会が来たときに,詳しく学んでもらいたい.

    なぜ機械学習をクラウドで行うのか?

    2010 年頃に始まった第三次 AI ブームのおかげで,学術研究だけでなく社会・ビジネスの文脈でも機械学習に高い関心が寄せられている. とくに,深層学習 (ディープラーニング) とよばれる多層のレイヤーからなるニューラルネットワークを用いたアルゴリズムは,画像認識や自然言語処理などの分野で圧倒的に高い性能を実現し,革命をもたらしている.

    深層学習の特徴は,なんといってもそのパラメータの多さである. 層が深くなるほど,層間のニューロンを結ぶ重みパラメータの数が増大していく. たとえば,最新の言語モデルである GPT-3 には1750 億個ものパラメータが含まれている. このような膨大なパラメータを有することで,深層学習は高い表現力と汎化性能を実現しているのである.

    GPT-3 に限らず,最近の SOTA (State-of-the-art) の性能を達成するニューラルネットワークでは,百万から億のオーダーのパラメータを内包することは頻繁になってきている. そのような巨大なニューラルネットを訓練 (最適化) させるのは,当然のことながら膨大な計算コストがかかる. 結果として,ひとつの計算機では丸一日以上の時間がかかる場合も珍しくない. 深層学習の発展の速度は目覚ましく,研究・ビジネス両方の観点からも,いかにスループットよくニューラルネットワークの最適化を行えるかが鍵となってくる. そのような問題を解決するのにとても有効な手段が,クラウドである! (#sec_first_ec2) でその片鱗を見たように,クラウドを使用することでゼロから数千に至るまでの数のインスタンスを動的に起動し,並列に計算を実行することができる. さらに,深層学習を加速させる目的で,深層学習の演算に専用設計された計算チップ (GPU など) がある. クラウドを利用すると,そのような専用計算チップも無尽蔵に利用することができる. 事実,先述した GPT-3 の学習も,詳細は明かされていないが,Microsoft 社のクラウドを使って行われたと報告されている.

    GPU による深層学習の高速化

    深層学習の計算で欠かすことのできない技術として, GPU (Graphics Processing Unit) について少し説明する.

    GPU は,その名のとおり,元々はコンピュータグラフィックスを出力するための専用計算チップである. CPU (Central Processing Unit) に対し,グラフィックスの演算に特化した設計がなされている. 身近なところでは, XBox や PS5 などのゲームコンソールなどに搭載されているし,ハイエンドなノート型・デスクトップ型計算機にも搭載されていることがある. コンピュータグラフィックスでは,スクリーンにアレイ状に並んだ数百万個の画素をビデオレート (30 fps) 以上で処理する必要がある. そのため,GPU はコアあたりの演算能力は比較的小さいかわりに,チップあたり数百から数千のコアを搭載しており (figure_title),スクリーンの画素を並列的に処理することで,リアルタイムでの描画を実現している.

    GPUのアーキテクチャ.GPUには数百から数千の独立した計算コアが搭載されている. (画像出典: https://devblogs.nvidia.com/nvidia-turing-architecture-in-depth/)

    このように,コンピュータグラフィクスの目的で生まれた GPU だが,2010 年前後から,その高い並列計算能力をグラフィックス以外の計算 (科学計算など) に用いるという流れ (General-purpose computing on GPU; GPGPU) が生まれた. GPU のコアは,その設計から,行列の計算など,単純かつ規則的な演算が得意であり,そのような演算に対しては数個程度のコアしかもたない CPU に比べて圧倒的に高い計算速度を実現することができる. 現在では GPGPU は分子動力学や気象シミュレーション,そして機械学習など多くの分野で使われている.

    ディープラーニングで最も頻繁に起こる演算が,ニューロンの出力を次の層のニューロンに伝える畳み込み (Convolution) 演算である (figure_title). 畳み込み演算は,まさに GPU が得意とする演算であり, CPU ではなく GPU を用いることで学習を飛躍的に (最大で数百倍程度) 加速させることができる.

    ニューラルネットワークにおける畳み込み演算.

    このように GPU は機械学習の計算で欠かせないものであるが,なかなか高価である. たとえば,科学計算・機械学習に専用設計された NVIDIA 社の Tesla V100 というチップは,一台で約百万円の価格が設定されている. 機械学習を始めるのに,いきなり百万円の投資はなかなか大きい. だが,クラウドを使えば,初期コスト0で GPU を使用することができる.

    機械学習を行うのに, V100 が必ずしも必要というわけではない. むしろ,研究者などでしばしば行われるのは,コンピュータゲームに使われるグラフィックス用の GPU を買ってきて (NVIDIA GeForce シリーズなど),開発のときはをそれを用いる,というアプローチである. グラフィックス用のいわゆる"コンシューマ GPU"は,市場の需要が大きいおかげで,10 万円前後の価格で購入することができる. V100 と比べると,コンシューマ GPU はコアの数が少なかったり,メモリーが小さかったりなどで劣る点があるが, それらを除いては計算能力にとくに制限があるわけではなく,開発の段階では十分な性能である場合がほとんどである. プログラムができあがって,ビッグデータの解析や,モデルをさらに大きくしたいときなどに,クラウドは有効だろう.

    クラウドで GPU を使うには, GPU が搭載された EC2 インスタンスタイプ (P3, P2, G3, G4 など) を選択しなければならない. table_title に,代表的な GPU 搭載のインスタンスタイプを挙げる (執筆時点での情報).

    GPUを搭載したEC2インスタンスタイプ
    InstanceGPUsGPU modelGPU Mem (GiB)vCPUMem (GiB)Price per hour ($)

    p3.2xlarge

    1

    NVIDIA V100

    16

    8

    61

    3.06

    p3n.16xlarge

    8

    NVIDIA V100

    128

    64

    488

    24.48

    p2.xlarge

    1

    NVIDIA K80

    12

    4

    61

    0.9

    g4dn.xlarge

    1

    NVIDIA T4

    16

    4

    16

    0.526

    table_title からわかるとおり, CPU のみのインスタンスと比べると少し高い価格設定になっている. また,古い世代の GPU (V100 に対しての K80) はより安価な価格で提供されている. 1 インスタンスあたりの GPU の搭載数は 1 台から最大で 8 台まで選択することが可能である.

    GPU を搭載した一番安いインスタンスタイプは, g4dn.xlarge であり,これには廉価かつ省エネルギー設計の NVIDIA T4 が搭載されている. 後のハンズオンでは,このインスタンスを使用して,ディープラーニングの計算を行ってみる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    V100 を一台搭載した p3.2xlarge の利用料金は一時間あたり $3.06 である. V100 が約百万円で売られていることを考えると,約 3000 時間 (= 124 日間),通算で計算を行った場合に,クラウドを使うよりも V100 を自分で買ったほうがお得になる,という計算になる (実際には,自前で V100 を用意する場合は, V100 だけでなく, CPU やネットワーク機器,電気使用料も必要なので,百万円よりもさらにコストがかかる).

    GPT-3 で使われた計算リソースの詳細は論文でも明かされていないのだが, Lambda 社のブログで興味深い考察が行われている (Lambda 社は機械学習に特化したクラウドサービスを提供している).

    記事によると,1750 億のパラメータを訓練するには,一台の GPU (NVIDIA V100) を用いた場合,342 年の月日と 460 万ドルのクラウド利用料が必要となる,とのことである. GPT-3 のチームは,複数の GPU に処理を分散することで現実的な時間のうちに訓練を完了させたのであろうが,このレベルのモデルになってくるとクラウド技術の限界を攻めないと達成できないことは確かである.

    深層学習を詳しく勉強したい人には以下の参考書を推薦したい. 深層学習の基礎的な概念や理論は普遍的であるが,この分野は日進月歩なので,常に最新の情報を取り入れることを忘れずに.

    ',25);function g(_,G,f,m,U,u){const e=a;return d(),n("div",null,[h,i(e,{readTime:"5",words:"1.4k"}),P])}const y=o(c,[["render",g]]);export{T as __pageData,y as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as r}from"./chunks/cnn.a8836fd9.js";import{_ as o,o as d,c as n,H as i,k as t,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"クラウドで行う科学計算・機械学習","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/scientific-computing.md","filePath":"development/aws/scientific-computing.md","lastUpdated":1699051935000}'),c={name:"development/aws/scientific-computing.md"},h=t("h1",{id:"クラウドで行う科学計算・機械学習",tabindex:"-1"},[s("クラウドで行う科学計算・機械学習 "),t("a",{class:"header-anchor",href:"#クラウドで行う科学計算・機械学習","aria-label":'Permalink to "クラウドで行う科学計算・機械学習"'},"​")],-1),P=l('

    計算機が発達した現代では,計算機によるシミュレーションやビッグデータの解析は,科学・エンジニアリングの研究の主要な柱である. これらの大規模な計算を実行するには,クラウドは最適である. 本章から始まる第二部では,どのようにしてクラウド上で科学計算を実行するのかを,ハンズオンとともに体験してもらう. 科学計算の具体的な題材として,今回は機械学習(深層学習)を取り上げる.

    なお,本書では PyTorch ライブラリを使って深層学習のアルゴリズムを実装するが,深層学習および PyTorch の知識は不要である. 講義ではなぜ・どうやって深層学習をクラウドで実行するかに主眼を置いているので,実行するプログラムの詳細には立ち入らない. 将来,自分で深層学習を使う機会が来たときに,詳しく学んでもらいたい.

    なぜ機械学習をクラウドで行うのか?

    2010 年頃に始まった第三次 AI ブームのおかげで,学術研究だけでなく社会・ビジネスの文脈でも機械学習に高い関心が寄せられている. とくに,深層学習 (ディープラーニング) とよばれる多層のレイヤーからなるニューラルネットワークを用いたアルゴリズムは,画像認識や自然言語処理などの分野で圧倒的に高い性能を実現し,革命をもたらしている.

    深層学習の特徴は,なんといってもそのパラメータの多さである. 層が深くなるほど,層間のニューロンを結ぶ重みパラメータの数が増大していく. たとえば,最新の言語モデルである GPT-3 には1750 億個ものパラメータが含まれている. このような膨大なパラメータを有することで,深層学習は高い表現力と汎化性能を実現しているのである.

    GPT-3 に限らず,最近の SOTA (State-of-the-art) の性能を達成するニューラルネットワークでは,百万から億のオーダーのパラメータを内包することは頻繁になってきている. そのような巨大なニューラルネットを訓練 (最適化) させるのは,当然のことながら膨大な計算コストがかかる. 結果として,ひとつの計算機では丸一日以上の時間がかかる場合も珍しくない. 深層学習の発展の速度は目覚ましく,研究・ビジネス両方の観点からも,いかにスループットよくニューラルネットワークの最適化を行えるかが鍵となってくる. そのような問題を解決するのにとても有効な手段が,クラウドである! (#sec_first_ec2) でその片鱗を見たように,クラウドを使用することでゼロから数千に至るまでの数のインスタンスを動的に起動し,並列に計算を実行することができる. さらに,深層学習を加速させる目的で,深層学習の演算に専用設計された計算チップ (GPU など) がある. クラウドを利用すると,そのような専用計算チップも無尽蔵に利用することができる. 事実,先述した GPT-3 の学習も,詳細は明かされていないが,Microsoft 社のクラウドを使って行われたと報告されている.

    GPU による深層学習の高速化

    深層学習の計算で欠かすことのできない技術として, GPU (Graphics Processing Unit) について少し説明する.

    GPU は,その名のとおり,元々はコンピュータグラフィックスを出力するための専用計算チップである. CPU (Central Processing Unit) に対し,グラフィックスの演算に特化した設計がなされている. 身近なところでは, XBox や PS5 などのゲームコンソールなどに搭載されているし,ハイエンドなノート型・デスクトップ型計算機にも搭載されていることがある. コンピュータグラフィックスでは,スクリーンにアレイ状に並んだ数百万個の画素をビデオレート (30 fps) 以上で処理する必要がある. そのため,GPU はコアあたりの演算能力は比較的小さいかわりに,チップあたり数百から数千のコアを搭載しており (figure_title),スクリーンの画素を並列的に処理することで,リアルタイムでの描画を実現している.

    GPUのアーキテクチャ.GPUには数百から数千の独立した計算コアが搭載されている. (画像出典: https://devblogs.nvidia.com/nvidia-turing-architecture-in-depth/)

    このように,コンピュータグラフィクスの目的で生まれた GPU だが,2010 年前後から,その高い並列計算能力をグラフィックス以外の計算 (科学計算など) に用いるという流れ (General-purpose computing on GPU; GPGPU) が生まれた. GPU のコアは,その設計から,行列の計算など,単純かつ規則的な演算が得意であり,そのような演算に対しては数個程度のコアしかもたない CPU に比べて圧倒的に高い計算速度を実現することができる. 現在では GPGPU は分子動力学や気象シミュレーション,そして機械学習など多くの分野で使われている.

    ディープラーニングで最も頻繁に起こる演算が,ニューロンの出力を次の層のニューロンに伝える畳み込み (Convolution) 演算である (figure_title). 畳み込み演算は,まさに GPU が得意とする演算であり, CPU ではなく GPU を用いることで学習を飛躍的に (最大で数百倍程度) 加速させることができる.

    ニューラルネットワークにおける畳み込み演算.

    このように GPU は機械学習の計算で欠かせないものであるが,なかなか高価である. たとえば,科学計算・機械学習に専用設計された NVIDIA 社の Tesla V100 というチップは,一台で約百万円の価格が設定されている. 機械学習を始めるのに,いきなり百万円の投資はなかなか大きい. だが,クラウドを使えば,初期コスト0で GPU を使用することができる.

    機械学習を行うのに, V100 が必ずしも必要というわけではない. むしろ,研究者などでしばしば行われるのは,コンピュータゲームに使われるグラフィックス用の GPU を買ってきて (NVIDIA GeForce シリーズなど),開発のときはをそれを用いる,というアプローチである. グラフィックス用のいわゆる"コンシューマ GPU"は,市場の需要が大きいおかげで,10 万円前後の価格で購入することができる. V100 と比べると,コンシューマ GPU はコアの数が少なかったり,メモリーが小さかったりなどで劣る点があるが, それらを除いては計算能力にとくに制限があるわけではなく,開発の段階では十分な性能である場合がほとんどである. プログラムができあがって,ビッグデータの解析や,モデルをさらに大きくしたいときなどに,クラウドは有効だろう.

    クラウドで GPU を使うには, GPU が搭載された EC2 インスタンスタイプ (P3, P2, G3, G4 など) を選択しなければならない. table_title に,代表的な GPU 搭載のインスタンスタイプを挙げる (執筆時点での情報).

    GPUを搭載したEC2インスタンスタイプ
    InstanceGPUsGPU modelGPU Mem (GiB)vCPUMem (GiB)Price per hour ($)

    p3.2xlarge

    1

    NVIDIA V100

    16

    8

    61

    3.06

    p3n.16xlarge

    8

    NVIDIA V100

    128

    64

    488

    24.48

    p2.xlarge

    1

    NVIDIA K80

    12

    4

    61

    0.9

    g4dn.xlarge

    1

    NVIDIA T4

    16

    4

    16

    0.526

    table_title からわかるとおり, CPU のみのインスタンスと比べると少し高い価格設定になっている. また,古い世代の GPU (V100 に対しての K80) はより安価な価格で提供されている. 1 インスタンスあたりの GPU の搭載数は 1 台から最大で 8 台まで選択することが可能である.

    GPU を搭載した一番安いインスタンスタイプは, g4dn.xlarge であり,これには廉価かつ省エネルギー設計の NVIDIA T4 が搭載されている. 後のハンズオンでは,このインスタンスを使用して,ディープラーニングの計算を行ってみる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    V100 を一台搭載した p3.2xlarge の利用料金は一時間あたり $3.06 である. V100 が約百万円で売られていることを考えると,約 3000 時間 (= 124 日間),通算で計算を行った場合に,クラウドを使うよりも V100 を自分で買ったほうがお得になる,という計算になる (実際には,自前で V100 を用意する場合は, V100 だけでなく, CPU やネットワーク機器,電気使用料も必要なので,百万円よりもさらにコストがかかる).

    GPT-3 で使われた計算リソースの詳細は論文でも明かされていないのだが, Lambda 社のブログで興味深い考察が行われている (Lambda 社は機械学習に特化したクラウドサービスを提供している).

    記事によると,1750 億のパラメータを訓練するには,一台の GPU (NVIDIA V100) を用いた場合,342 年の月日と 460 万ドルのクラウド利用料が必要となる,とのことである. GPT-3 のチームは,複数の GPU に処理を分散することで現実的な時間のうちに訓練を完了させたのであろうが,このレベルのモデルになってくるとクラウド技術の限界を攻めないと達成できないことは確かである.

    深層学習を詳しく勉強したい人には以下の参考書を推薦したい. 深層学習の基礎的な概念や理論は普遍的であるが,この分野は日進月歩なので,常に最新の情報を取り入れることを忘れずに.

    ',25);function g(_,G,f,m,U,u){const e=a;return d(),n("div",null,[h,i(e,{readTime:"5",words:"1.4k"}),P])}const y=o(c,[["render",g]]);export{T as __pageData,y as default}; diff --git a/assets/development_aws_scientific-computing.md.1b192c5b.lean.js b/assets/development_aws_scientific-computing.md.194874e2.lean.js similarity index 94% rename from assets/development_aws_scientific-computing.md.1b192c5b.lean.js rename to assets/development_aws_scientific-computing.md.194874e2.lean.js index f3a42c7b..4ff6035b 100644 --- a/assets/development_aws_scientific-computing.md.1b192c5b.lean.js +++ b/assets/development_aws_scientific-computing.md.194874e2.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as r}from"./chunks/cnn.a8836fd9.js";import{_ as o,o as d,c as n,H as i,k as t,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"クラウドで行う科学計算・機械学習","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/scientific-computing.md","filePath":"development/aws/scientific-computing.md","lastUpdated":1695377563000}'),c={name:"development/aws/scientific-computing.md"},h=t("h1",{id:"クラウドで行う科学計算・機械学習",tabindex:"-1"},[s("クラウドで行う科学計算・機械学習 "),t("a",{class:"header-anchor",href:"#クラウドで行う科学計算・機械学習","aria-label":'Permalink to "クラウドで行う科学計算・機械学習"'},"​")],-1),P=l("",25);function g(_,G,f,m,U,u){const e=a;return d(),n("div",null,[h,i(e,{readTime:"5",words:"1.4k"}),P])}const y=o(c,[["render",g]]);export{T as __pageData,y as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as p,a as r}from"./chunks/cnn.a8836fd9.js";import{_ as o,o as d,c as n,H as i,k as t,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const T=JSON.parse('{"title":"クラウドで行う科学計算・機械学習","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/scientific-computing.md","filePath":"development/aws/scientific-computing.md","lastUpdated":1699051935000}'),c={name:"development/aws/scientific-computing.md"},h=t("h1",{id:"クラウドで行う科学計算・機械学習",tabindex:"-1"},[s("クラウドで行う科学計算・機械学習 "),t("a",{class:"header-anchor",href:"#クラウドで行う科学計算・機械学習","aria-label":'Permalink to "クラウドで行う科学計算・機械学習"'},"​")],-1),P=l("",25);function g(_,G,f,m,U,u){const e=a;return d(),n("div",null,[h,i(e,{readTime:"5",words:"1.4k"}),P])}const y=o(c,[["render",g]]);export{T as __pageData,y as default}; diff --git a/assets/development_aws_serverless.md.715b8a8d.js b/assets/development_aws_serverless.md.a89d6134.js similarity index 99% rename from assets/development_aws_serverless.md.715b8a8d.js rename to assets/development_aws_serverless.md.a89d6134.js index 4d10bf09..a276f492 100644 --- a/assets/development_aws_serverless.md.715b8a8d.js +++ b/assets/development_aws_serverless.md.a89d6134.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,a as o,b as s,c as n,d as p}from"./chunks/s3_vs_filesystem.fd65005d.js";import{_ as d,o as l,c as i,H as c,k as e,a as m,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const A=JSON.parse('{"title":"Serverless architecture","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/serverless.md","filePath":"development/aws/serverless.md","lastUpdated":1695377563000}'),g={name:"development/aws/serverless.md"},u=e("h1",{id:"serverless-architecture",tabindex:"-1"},[m("Serverless architecture "),e("a",{class:"header-anchor",href:"#serverless-architecture","aria-label":'Permalink to "Serverless architecture"'},"​")],-1),b=h('

    サーバーレスアーキテクチャ (Serverless architecture) あるいは サーバーレスコンピューティング (Serverless computing) とは,従来とは全く異なるアプローチに基づくクラウドシステムの設計方法である. 歴史的には, AWS が 2014 年に発表した Lamba がサーバーレスアーキテクチャの先駆けとされている. その後, Google や Microsoft などのクラウドプラットフォームも同様の機能の提供を開始している. サーバーレスアーキテクチャの利点は,スケーラブルなクラウドシステムを安価かつ簡易に作成できる点であり,近年いたるところで導入が進んでいる.

    Serverless とは,文字どおりの意味としてはサーバーなしで計算をするということになるが,それは一体どういう意味だろうか? サーバーレスについて説明するためには,まずは従来的な, "serverful" とよばれるようなシステムについて解説しなければならない.

    Serverful クラウド (従来型)

    従来的なクラウドシステムのスケッチを figure_title に示す. クライアントから送信されたリクエストは,最初に API サーバーに送られる. API サーバーでは,リクエストの内容に応じてタスクが実行される. タスクには,API サーバーだけで完結できるものもあるが,多くの場合,データベースの読み書きが必要である. データベースには,データベース専用の独立したサーバーマシンが用いられることが一般的である. また,画像や動画などの容量の大きいデータは,また別のストレージサーバーに保存されることが多い. これらの API サーバー,データベースサーバー,ストレージサーバーはそれぞれ独立したサーバーマシンであり, AWS の言葉では EC2 による仮想インスタンスを想定してもらったらよい.

    多くのウェブサービスでは,多数のクライアントからのリクエストを処理するため,複数のサーバーマシンがクラウド内で起動し,負荷を分散するような設計がなされている. クライアントから来たリクエストを計算容量に余裕のあるサーバーに振り分けるような操作を Load balancing とよび,そのような操作を担当するマシンのことを Load balancer という.

    計算負荷を分散する目的で多数のインスタンスを起動するのはよいのだが,計算負荷が小さすぎてアイドリング状態にあるようではコストと電力の無駄遣いである. したがって,すべてのサーバーが常に目標とする計算負荷を維持するよう,計算の負荷に応じてクラスター内の仮想サーバーの数を動的に増減させるような仕組みが必要である. そのような仕組みをクラスターのスケーリングとよび,負荷の増大に応答して新しい仮想インスタンスをクラスターに追加する操作を scale-out,負荷の減少に応答してインスタンスをシャットダウンする操作を scale-in とよぶ. クラスターのスケーリングは, API サーバーではもちろんのこと,データベースサーバー・ストレージサーバーでも必要になる. ストレージサーバーでは,例えば頻繁にアクセスされるデータはキャッシュ領域に保存したり,データのコピーを複数作るなどのスケーリングが行われる. データベースサーバーも同様に,頻繁にアクセスされるデータのアクセスがパンクしてしまわないよう,分散的な処理が必要となる. このように,クラウドシステム内すべての箇所で,負荷が均一になるような調整が必要であり,開発者は多くの時間をそのチューニングに費やさなければならない. また,サービスの利用者の数などに応じてスケーリングの設定は常に見直される必要があり,継続的な開発が要求される.

    さらに問題を複雑にするのは,API サーバーで処理されるべきタスクが,非一様な点である. 非一様であるとは,たとえばタスク A は 3000 ミリ秒の実行時間と 512MB のメモリーを消費し,別のタスク B は 1000 ミリ秒の実行時間と 128MB のメモリーを消費する,というような状況を指している. 一つのサーバーマシンが計算負荷が異なる複数のタスクを処理する場合,クラスターのスケーリングはより複雑になる. この状況をシンプルにするために,1サーバーで実行するタスクは1種類に限る,という設計も可能であるが,そうするとで生まれる弊害も多い (ほとんど使われないタスクに対してもサーバー一台をまるまる割り当てなければならない = ほとんどアイドリング状態になってしまう,など).

    Serverful なクラウドシステム

    Serverless クラウドへ

    Serverful クラウド (従来型) で議論したように,クラスターのスケーリングはクラウドシステムの経済的効率とシステムの安定性を最大化するために必須の作業である. それを反映して,多くの開発者の時間が投資されてきた.

    クラスターのスケーリングはすべての開発者が何度も繰り返し行ってきた作業であり,いくつかの側面をテンプレート化し,共通化することができたならば開発のコストを大幅に削減できるだろう. それを実現するには,根本的なレベルからクラウドシステムの設計を考え直す必要がある. スケーリングを前提として考えることで,もっとシンプルで見通しがよいクラウドシステムの設計の仕組みはないだろうか? そのような動機が,サーバーレスアーキテクチャが誕生する背後にあった.

    従来の serverful なシステムでの最大の問題点は,サーバーをまるまる占有してしまうという点にある. すなわち, EC2 インスタンスを起動したとき,そのインスタンスは起動したユーザーだけが使えるものであり,計算のリソース (CPU や RAM) が独占的に割り当てられた状態になる. 固定した計算資源の割り当てがされてしまっているので,インスタンスの計算負荷が 0%であろうが 100%であろうが,均一の使用料金が起動時間に比例して発生する.

    サーバーレスアーキテクチャは,このような 独占的に割り当てられた計算リソースというものを完全に廃止することを出発点とする. サーバーレスアーキテクチャでは,計算のリソースは,クラウドプロバイダーがすべて管理する. クライアントは,仮想インスタンスを一台まるごと借りるのではなく,計算のタスクの需要が生まれる毎に,実行したいプログラム・コマンドをクラウドに提出する. クラウドプロバイダーは,自身のもつ巨大な計算リソースから空きを探し,提出されたプログラムを実行し,実行結果をクライアントに返す. 言い換えると,計算リソースのスケーリングやアロケーションなどはクラウドプロバイダーが一手に引き受け,ユーザーはジョブをサブミットすることに注力する,という枠組みである. これを図示すると, figure_title のようになる.

    従来のクラウドと Serverless クラウドの比較

    サーバーレスクラウドでは,スケーリングはすべてクラウドプロバイダーが引き受けるので,スケーラビリティーが保証されている. クライアントが同時に大量のタスクを送信した場合でも,クラウドプロバイダー側の独自の仕組みによってすべてのタスクが遅延なく実行される. また,サーバーレスクラウドを利用することで,クラウドのコストは実際に使用した計算の総量 (稼働時間) で決定されることになる. これは,計算の実行総量に関わらずインスタンスの起動時間で料金が決定されていた従来のシステムと比べて大きな違いである.

    サーバーレスクラウドは,従来のクラウドとは根本から異なったアプローチなので,コードの書き方やシステムの設計が大きく異なる. サーバーレスクラウドを開発・運用するには,サーバーレス固有の概念や用語に精通している必要がある. 以降では,実際にクラウドを動かしながら,サーバーレスをより具体的に体験していこう.

    従来型の(仮想インスタンスをたくさん起動するような)クラウドシステムは,賃貸と似ているかもしれない. 部屋を借りるというのは,その部屋でどれだけの時間を過ごそうが,月々の家賃は一定である. 同様に,仮想サーバーも,それがどれほどの計算を行っているかに関わらず,一定の料金が時間ごとに発生する.

    一方で,サーバーレスクラウドは,電気・水道・ガス料金 と似ている. こちらは,実際に使用した量に比例して料金が決定されている. サーバーレスクラウドも,実際に計算を行った総時間で料金が決まる仕組みになっている.

    サーバーレスクラウドを構成するコンポーネント

    サーバーレスアーキテクチャの概要がわかってきたところで,ここでは AWS においてサーバーレスクラウドを構成する様々なコンポーネントを紹介していこう. 特に, Lambda, S3, DynamoDB を取り上げ,解説する (figure_title). サーバーレスクラウドは,これらのコンポーネントを統合することで一つのシステムが出来上がる. ここでは, Lambda,S3,DynamoDB を利用する際に押さえておかなければならない知識を一通り説明しきる都合上,具体的なイメージがわきにくいかもしれない. が,続く (#sec_intro_serverless) でそれぞれについてハンズオン形式で演習を行うので,そこでさらに理解を深めれば大丈夫である.

    Lambda, S3, DynamoDB のアイコン

    Lambda

    AWS でサーバーレスコンピューティングの中心を担うのが, Lambda である. Lambda の使い方を figure_title に図示している. Lambda の仕組みはシンプルで,まずユーザーは実行したいプログラムのコードを事前に登録しておく. プログラムは, Python, Node.js, Ruby などの主要な言語がサポートされている. Lambda に登録されたひとつひとつのプログラムを関数 (Function) とよぶ. そして,関数を実行したいときに,invoke コマンドを Lambda に送信する. Lambda では, invoke のリクエストを受け取るとただちに (数ミリセカンドから数百ミリセカンド程度の時間で) プログラムの実行を開始する. そして,実行結果をクライアントやその他の計算機に返す.

    AWS Lambda

    このように,Lambda では占有された仮想インスタンスは存在せず,実行を待っているプログラムだけがある状態である. invoke のリクエストに応じて,プログラムが AWS の巨大な計算機プールのどこかに配置され,実行される. 同時に複数のリクエストが来た場合でも, AWS はそれらを実行するための計算リソースを割り当て,並列的に処理を行ってくれる. 原理上は,数千から数万のリクエストが同時に来たとしても, Lambda はそれらを同時に実行することができる. このような,占有された仮想サーバーの存在なしに,動的に関数を実行するサービスのことを総称して FaaS (Function as a Service) とよぶ.

    Lambda ではそれぞれの関数につき, 128MB から 10240MB のメモリーを使用することができる (執筆時点の仕様). また,実効的な CPU のパワーはメモリーの量に比例する形で割り当てられる. すなわち,タスクに割り当てたメモリーの量が多ければ多いほど,より多くの CPU リソースが割り当てられることになる (しかし, RAM と CPU パワーの具体的な換算表は AWS からは公開されていない). 実行時間は 100 ミリ秒の単位で記録され,実行時間に比例して料金が決定される. table_title は Lambda の利用料金表である (執筆時点で ap-north-east1 リージョンを選択した場合).

    Lambda の料金表
    Memory (MB)Price per 100ms

    128

    $0.0000002083

    512

    $0.0000008333

    1024

    $0.0000016667

    3008

    $0.0000048958

    実行時間に比例する料金に追加して,リクエストを送信するごとに発生する料金が設定されている. これは,百万回のリクエストにつき $0.2 である. たとえば, 128MB のメモリーを使用する関数を,それぞれ 200 ミリ秒,合計で 100 万回実行した場合, 0.0000002083 * 2 * 10^6 + 0.2 = $0.6 の料金となる. ウェブサーバーのデータベースの更新など簡単な計算であれば,200 ミリ秒程度で実行できる関数も多いことから,100 万回データベースの更新を行ったとしても,たった $0.6 しかコストが発生しないことになる. また,コードが実行されず待機状態になっている場合は,発生する料金は 0 である. このように,実際に意味のある処理が行われた時間にのみ,料金が発生する仕組みになっている.

    Lambda は比較的短時間で完了する,反復性の高いタスクの実行に向いている. データベースの読み書きはその典型的な例であるが,そのほかにも,画像のサイズをトリミングしたり,サーバーサイドで定期的に実行されるメンテナンス処理などの利用が考えられる. また,複数の Lambda をリレー式に繋げることも可能で,シンプルな処理を組み合わせることで複雑なロジックを表現することができる.

    上述の Lambda の料金計算は,説明のためコストに寄与する要素をいくつか省いている点は承知いただきたい. 例えば, DynamoDB の読み書きに関する料金や,ネットワークの通信にかかわるコストが考慮されていない.

    サーバーレスストレージ: S3

    サーバーレスの概念は,ストレージにも拡張されている.

    従来的なストレージ (ファイルシステム) では,必ずホストとなるマシンと OS が存在しなければならない. したがって,それほどパワーは必要ないまでも,ある程度の CPU リソースを割かなければならない. また,従来的なファイルシステムでは,データ領域のサイズは最初にディスクを初期化するときに決めなければならず,後から容量を増加させることはしばしば困難である (ZFS などのファイルシステムを使えばある程度は自由にファイルシステムのサイズを変更することは可能である). よって,従来的なクラウドでは,ストレージを借りる際にはあらかじめディスクのサイズを指定せねばならず,ディスクの中身が空であろうと満杯であろうと,同じ利用料金が発生することになる (figure_title).

    Simple Storage Service (S3) は,サーバーレスなストレージシステムを提供する (figure_title). S3 は従来的なストレージシステムと異なり, OS に"マウントする”という概念はない. 基本的に API を通じてデータの読み書きの操作が行われる. また,データの冗長化や暗号化,バックアップの作成など,通常ならば OS と CPU が介在しなければならない操作も, API を通じて行うことができる. S3 では事前に決められたディスク領域のサイズはなく,データを入れれば入れた分だけ,保存領域は拡大していく (仕様上はペタバイトスケールのデータを保存することが可能である). ストレージにかかる料金は,保存してあるデータの総容量で決定される.

    S3 と従来的なファイルシステムの比較

    S3 を利用する際に,料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 説明のため主要な事項のみ取り出している. 詳細は 公式ドキュメンテーション "Amazon S3 pricing" を参照).

    S3 の利用料金
    項目料金

    Data storage (First 50TB)

    $0.023 per GB per month

    PUT, COPY, POST, LIST requests (per 1,000 requests)

    $0.005

    GET, SELECT, and all other requests (per 1,000 requests)

    $0.0004

    Data Transfer IN To Amazon S3 From Internet

    $0

    Data Transfer OUT From Amazon S3 To Internet

    $0.09 per GB

    第一に,データの保存には $0.025 per GB のコストが月ごとに発生する. したがって,1000GB のデータを S3 に一ヵ月保存した場合, $25 の料金が発生することになる. また,PUT, COPY, POST などのリクエスト (=データを書き込む操作) に対しては,データ容量に関係なく,1000 回ごとに $0.005 のコストが発生する. GET, SELECT などのリクエスト (=データを読み込む操作) に対しては,1000 回ごとに $0.0004 のコストが発生する. また, S3 はデータを外に取り出す際の通信にもコストが生じる. 執筆時点では,S3 からインターネットを通じて外部にデータを転送 (data-out) すると $0.09 per GB のコストが発生する. データをインターネットを通じて S3 に入れる (data-in) 通信は無料で行える. また, AWS の 同じ Region 内のサービス (Lambda や EC2 など) にデータを転送するのは無料である. AWS のリージョンをまたいだデータの転送にはコストが発生する. いずれにせよ,サーバーレスの概念に則り,すべての料金が従量課金制で決定される設定になっている.

    サーバーレスデータベース: DynamoDB

    サーバーレスの概念は,データベースにも適用することができる.

    ここでいうデータベースとは, Web サービスなどにおけるユーザーや商品の情報を記録しておくための保存領域のことを指している. 従来的に有名なデータベースとしては MySQL, PostgreSQL, MongoDB などが挙げられる. データベースと普通のストレージの違いは,データの検索機能にある. 普通のストレージではデータは単純にディスクに書き込まれるだけだが, データベースでは検索がより効率的になるようなデータの配置がされたり, 頻繁にアクセスされるデータはメモリーにキャッシュされるなどの機能が備わっている. これにより,巨大なデータの中から,興味のある要素を高速に取得することができる.

    このような検索機能を実現するには,当然 CPU の存在が必須である. したがって,従来的なデータベースを構築する際は,ストレージ領域に加えて,たくさんの CPU コアを搭載したマシンが用いられることが多い. また,データベースが巨大な場合は複数マシンにまたがった分散型のシステムが設計される. 分散型システムの場合は, Serverful クラウド (従来型) で議論したようにデータベースへのアクセス負荷に応じて適切なスケーリングがなされる必要がある.

    DynamoDB は, AWS が提供しているサーバーレスな分散型データベースである. サーバーレスであるので,占有されたデータベース用仮想インスタンスは存在せず, API を通じてデータの書き込み・読み出し・検索などの操作を行う. S3 と同様に,データ保存領域の上限は定められておらず,データを入れれば入れた分だけ,保存領域は拡大していく. また,データベースへの負荷が増減したときのスケーリングは, DynamoDB が自動で行うので,ユーザーは心配する必要はない.

    DynamoDB での利用料金の計算はやや複雑なのだが, "On-demand Capacity" というモードで使用した場合の料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 詳細は 公式ドキュメンテーション "Pricing for On-Demand Capacity" を参照).

    DynamoDB の利用料金
    項目料金

    Write request units

    $1.25 per million write request units

    Read request units

    $0.25 per million read request units

    Data storage

    $0.25 per GB-month

    DynamoDB ではデータの書き込み操作の単位を write request unit とよび,データの読み込み操作の単位を read request unit とよぶ. 基本的に, 1kB 以下のデータを一度書き込むと 1 write request unit を消費し,4kB 以下のデータを一度読み込むと 1 read request unit を消費する (詳しくは 公式ドキュメンテーション "Read/Write Capacity Mode" を参照のこと). write request units は 100 万回ごとに $1.25, read request units は 100 万回ごとに $0.25 のコストが設定されている. また,保存されたデータ容量に対して $0.25 per GB のコストが月ごとに発生する. DynamoDB は高速な検索機能などを備えたデータベースであるので, GB あたりのストレージコストは S3 に比べ 10 倍程度高い. DynamoDB のデータの転送に関わるコストは,同じリージョン内ならば data-in,data-out ともに $0 である. リージョンをまたいだ通信には別途コストが発生する.

    その他のサーバーレスクラウドの構成要素

    以上で紹介した Lambda, S3, DynamoDB がサーバーレスクラウドの中で最も使用する頻度が高いサービスになる. その他のサーバーレスクラウドの構成要素を以下に列挙する. いくつかについては,今後のハンズオンを行う中で改めて解説を行う.

    • API Gateway: API を構築する際のルーティングを担う. (#sec_bashoutter) で取り上げる.

    • Fargate: (#sec_fargate_qabot) で触れた Fargate も,サーバーレスクラウドの要素の一部である. Lambda との違いは,Lambda よりも大容量のメモリーや CPU を要するような計算などを行うことができる点が挙げられる.

    • Simple Notification Service (SNS): サーバーレスのサービス間でイベントをやり取りするためのサービス.

    • Step Functions: サーバーレスのサービス間のオーケストレーションを担う.

    サーバーレスアーキテクチャは万能か?

    この問いへの答えは,筆者は NO であると考える.

    ここまで,サーバーレスの利点を強調して説明をしてきたが,まだまだ新しい技術なだけに,欠点,あるいはサーバーフルなシステムに劣る点は数多くある.

    大きな欠点を一つあげるとすれば,サーバーレスのシステムは各クラウドプラットフォームに固有なものなので,特定のプラットフォームでしか運用できないシステムになってしまう点であろう. AWS で作成したサーバーレスのシステムを, Google のクラウドに移植するには,かなり大掛かりなプログラムの書き換えが必要になる. 一方, serverful なシステムであれば,プラットフォーム間のマイグレーションは比較的簡単に行うことができる. クラウドプロバイダーとしては,自社のシステムへの依存度を強めることで,顧客を離さないようにするという狙いがあるのだろう…

    その他,サーバーレスコンピューティングの欠点や今後の課題などは,次の論文で詳しく議論されている. 興味のある読者はぜひ読んでいただきたい.

    ',55);function f(_,S,v,y,q,P){const a=t;return l(),i("div",null,[u,c(a,{readTime:"9",words:"2.4k"}),b])}const L=d(g,[["render",f]]);export{A as __pageData,L as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,a as o,b as s,c as n,d as p}from"./chunks/s3_vs_filesystem.fd65005d.js";import{_ as d,o as l,c as i,H as c,k as e,a as m,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const A=JSON.parse('{"title":"Serverless architecture","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/serverless.md","filePath":"development/aws/serverless.md","lastUpdated":1699051935000}'),g={name:"development/aws/serverless.md"},u=e("h1",{id:"serverless-architecture",tabindex:"-1"},[m("Serverless architecture "),e("a",{class:"header-anchor",href:"#serverless-architecture","aria-label":'Permalink to "Serverless architecture"'},"​")],-1),b=h('

    サーバーレスアーキテクチャ (Serverless architecture) あるいは サーバーレスコンピューティング (Serverless computing) とは,従来とは全く異なるアプローチに基づくクラウドシステムの設計方法である. 歴史的には, AWS が 2014 年に発表した Lamba がサーバーレスアーキテクチャの先駆けとされている. その後, Google や Microsoft などのクラウドプラットフォームも同様の機能の提供を開始している. サーバーレスアーキテクチャの利点は,スケーラブルなクラウドシステムを安価かつ簡易に作成できる点であり,近年いたるところで導入が進んでいる.

    Serverless とは,文字どおりの意味としてはサーバーなしで計算をするということになるが,それは一体どういう意味だろうか? サーバーレスについて説明するためには,まずは従来的な, "serverful" とよばれるようなシステムについて解説しなければならない.

    Serverful クラウド (従来型)

    従来的なクラウドシステムのスケッチを figure_title に示す. クライアントから送信されたリクエストは,最初に API サーバーに送られる. API サーバーでは,リクエストの内容に応じてタスクが実行される. タスクには,API サーバーだけで完結できるものもあるが,多くの場合,データベースの読み書きが必要である. データベースには,データベース専用の独立したサーバーマシンが用いられることが一般的である. また,画像や動画などの容量の大きいデータは,また別のストレージサーバーに保存されることが多い. これらの API サーバー,データベースサーバー,ストレージサーバーはそれぞれ独立したサーバーマシンであり, AWS の言葉では EC2 による仮想インスタンスを想定してもらったらよい.

    多くのウェブサービスでは,多数のクライアントからのリクエストを処理するため,複数のサーバーマシンがクラウド内で起動し,負荷を分散するような設計がなされている. クライアントから来たリクエストを計算容量に余裕のあるサーバーに振り分けるような操作を Load balancing とよび,そのような操作を担当するマシンのことを Load balancer という.

    計算負荷を分散する目的で多数のインスタンスを起動するのはよいのだが,計算負荷が小さすぎてアイドリング状態にあるようではコストと電力の無駄遣いである. したがって,すべてのサーバーが常に目標とする計算負荷を維持するよう,計算の負荷に応じてクラスター内の仮想サーバーの数を動的に増減させるような仕組みが必要である. そのような仕組みをクラスターのスケーリングとよび,負荷の増大に応答して新しい仮想インスタンスをクラスターに追加する操作を scale-out,負荷の減少に応答してインスタンスをシャットダウンする操作を scale-in とよぶ. クラスターのスケーリングは, API サーバーではもちろんのこと,データベースサーバー・ストレージサーバーでも必要になる. ストレージサーバーでは,例えば頻繁にアクセスされるデータはキャッシュ領域に保存したり,データのコピーを複数作るなどのスケーリングが行われる. データベースサーバーも同様に,頻繁にアクセスされるデータのアクセスがパンクしてしまわないよう,分散的な処理が必要となる. このように,クラウドシステム内すべての箇所で,負荷が均一になるような調整が必要であり,開発者は多くの時間をそのチューニングに費やさなければならない. また,サービスの利用者の数などに応じてスケーリングの設定は常に見直される必要があり,継続的な開発が要求される.

    さらに問題を複雑にするのは,API サーバーで処理されるべきタスクが,非一様な点である. 非一様であるとは,たとえばタスク A は 3000 ミリ秒の実行時間と 512MB のメモリーを消費し,別のタスク B は 1000 ミリ秒の実行時間と 128MB のメモリーを消費する,というような状況を指している. 一つのサーバーマシンが計算負荷が異なる複数のタスクを処理する場合,クラスターのスケーリングはより複雑になる. この状況をシンプルにするために,1サーバーで実行するタスクは1種類に限る,という設計も可能であるが,そうするとで生まれる弊害も多い (ほとんど使われないタスクに対してもサーバー一台をまるまる割り当てなければならない = ほとんどアイドリング状態になってしまう,など).

    Serverful なクラウドシステム

    Serverless クラウドへ

    Serverful クラウド (従来型) で議論したように,クラスターのスケーリングはクラウドシステムの経済的効率とシステムの安定性を最大化するために必須の作業である. それを反映して,多くの開発者の時間が投資されてきた.

    クラスターのスケーリングはすべての開発者が何度も繰り返し行ってきた作業であり,いくつかの側面をテンプレート化し,共通化することができたならば開発のコストを大幅に削減できるだろう. それを実現するには,根本的なレベルからクラウドシステムの設計を考え直す必要がある. スケーリングを前提として考えることで,もっとシンプルで見通しがよいクラウドシステムの設計の仕組みはないだろうか? そのような動機が,サーバーレスアーキテクチャが誕生する背後にあった.

    従来の serverful なシステムでの最大の問題点は,サーバーをまるまる占有してしまうという点にある. すなわち, EC2 インスタンスを起動したとき,そのインスタンスは起動したユーザーだけが使えるものであり,計算のリソース (CPU や RAM) が独占的に割り当てられた状態になる. 固定した計算資源の割り当てがされてしまっているので,インスタンスの計算負荷が 0%であろうが 100%であろうが,均一の使用料金が起動時間に比例して発生する.

    サーバーレスアーキテクチャは,このような 独占的に割り当てられた計算リソースというものを完全に廃止することを出発点とする. サーバーレスアーキテクチャでは,計算のリソースは,クラウドプロバイダーがすべて管理する. クライアントは,仮想インスタンスを一台まるごと借りるのではなく,計算のタスクの需要が生まれる毎に,実行したいプログラム・コマンドをクラウドに提出する. クラウドプロバイダーは,自身のもつ巨大な計算リソースから空きを探し,提出されたプログラムを実行し,実行結果をクライアントに返す. 言い換えると,計算リソースのスケーリングやアロケーションなどはクラウドプロバイダーが一手に引き受け,ユーザーはジョブをサブミットすることに注力する,という枠組みである. これを図示すると, figure_title のようになる.

    従来のクラウドと Serverless クラウドの比較

    サーバーレスクラウドでは,スケーリングはすべてクラウドプロバイダーが引き受けるので,スケーラビリティーが保証されている. クライアントが同時に大量のタスクを送信した場合でも,クラウドプロバイダー側の独自の仕組みによってすべてのタスクが遅延なく実行される. また,サーバーレスクラウドを利用することで,クラウドのコストは実際に使用した計算の総量 (稼働時間) で決定されることになる. これは,計算の実行総量に関わらずインスタンスの起動時間で料金が決定されていた従来のシステムと比べて大きな違いである.

    サーバーレスクラウドは,従来のクラウドとは根本から異なったアプローチなので,コードの書き方やシステムの設計が大きく異なる. サーバーレスクラウドを開発・運用するには,サーバーレス固有の概念や用語に精通している必要がある. 以降では,実際にクラウドを動かしながら,サーバーレスをより具体的に体験していこう.

    従来型の(仮想インスタンスをたくさん起動するような)クラウドシステムは,賃貸と似ているかもしれない. 部屋を借りるというのは,その部屋でどれだけの時間を過ごそうが,月々の家賃は一定である. 同様に,仮想サーバーも,それがどれほどの計算を行っているかに関わらず,一定の料金が時間ごとに発生する.

    一方で,サーバーレスクラウドは,電気・水道・ガス料金 と似ている. こちらは,実際に使用した量に比例して料金が決定されている. サーバーレスクラウドも,実際に計算を行った総時間で料金が決まる仕組みになっている.

    サーバーレスクラウドを構成するコンポーネント

    サーバーレスアーキテクチャの概要がわかってきたところで,ここでは AWS においてサーバーレスクラウドを構成する様々なコンポーネントを紹介していこう. 特に, Lambda, S3, DynamoDB を取り上げ,解説する (figure_title). サーバーレスクラウドは,これらのコンポーネントを統合することで一つのシステムが出来上がる. ここでは, Lambda,S3,DynamoDB を利用する際に押さえておかなければならない知識を一通り説明しきる都合上,具体的なイメージがわきにくいかもしれない. が,続く (#sec_intro_serverless) でそれぞれについてハンズオン形式で演習を行うので,そこでさらに理解を深めれば大丈夫である.

    Lambda, S3, DynamoDB のアイコン

    Lambda

    AWS でサーバーレスコンピューティングの中心を担うのが, Lambda である. Lambda の使い方を figure_title に図示している. Lambda の仕組みはシンプルで,まずユーザーは実行したいプログラムのコードを事前に登録しておく. プログラムは, Python, Node.js, Ruby などの主要な言語がサポートされている. Lambda に登録されたひとつひとつのプログラムを関数 (Function) とよぶ. そして,関数を実行したいときに,invoke コマンドを Lambda に送信する. Lambda では, invoke のリクエストを受け取るとただちに (数ミリセカンドから数百ミリセカンド程度の時間で) プログラムの実行を開始する. そして,実行結果をクライアントやその他の計算機に返す.

    AWS Lambda

    このように,Lambda では占有された仮想インスタンスは存在せず,実行を待っているプログラムだけがある状態である. invoke のリクエストに応じて,プログラムが AWS の巨大な計算機プールのどこかに配置され,実行される. 同時に複数のリクエストが来た場合でも, AWS はそれらを実行するための計算リソースを割り当て,並列的に処理を行ってくれる. 原理上は,数千から数万のリクエストが同時に来たとしても, Lambda はそれらを同時に実行することができる. このような,占有された仮想サーバーの存在なしに,動的に関数を実行するサービスのことを総称して FaaS (Function as a Service) とよぶ.

    Lambda ではそれぞれの関数につき, 128MB から 10240MB のメモリーを使用することができる (執筆時点の仕様). また,実効的な CPU のパワーはメモリーの量に比例する形で割り当てられる. すなわち,タスクに割り当てたメモリーの量が多ければ多いほど,より多くの CPU リソースが割り当てられることになる (しかし, RAM と CPU パワーの具体的な換算表は AWS からは公開されていない). 実行時間は 100 ミリ秒の単位で記録され,実行時間に比例して料金が決定される. table_title は Lambda の利用料金表である (執筆時点で ap-north-east1 リージョンを選択した場合).

    Lambda の料金表
    Memory (MB)Price per 100ms

    128

    $0.0000002083

    512

    $0.0000008333

    1024

    $0.0000016667

    3008

    $0.0000048958

    実行時間に比例する料金に追加して,リクエストを送信するごとに発生する料金が設定されている. これは,百万回のリクエストにつき $0.2 である. たとえば, 128MB のメモリーを使用する関数を,それぞれ 200 ミリ秒,合計で 100 万回実行した場合, 0.0000002083 * 2 * 10^6 + 0.2 = $0.6 の料金となる. ウェブサーバーのデータベースの更新など簡単な計算であれば,200 ミリ秒程度で実行できる関数も多いことから,100 万回データベースの更新を行ったとしても,たった $0.6 しかコストが発生しないことになる. また,コードが実行されず待機状態になっている場合は,発生する料金は 0 である. このように,実際に意味のある処理が行われた時間にのみ,料金が発生する仕組みになっている.

    Lambda は比較的短時間で完了する,反復性の高いタスクの実行に向いている. データベースの読み書きはその典型的な例であるが,そのほかにも,画像のサイズをトリミングしたり,サーバーサイドで定期的に実行されるメンテナンス処理などの利用が考えられる. また,複数の Lambda をリレー式に繋げることも可能で,シンプルな処理を組み合わせることで複雑なロジックを表現することができる.

    上述の Lambda の料金計算は,説明のためコストに寄与する要素をいくつか省いている点は承知いただきたい. 例えば, DynamoDB の読み書きに関する料金や,ネットワークの通信にかかわるコストが考慮されていない.

    サーバーレスストレージ: S3

    サーバーレスの概念は,ストレージにも拡張されている.

    従来的なストレージ (ファイルシステム) では,必ずホストとなるマシンと OS が存在しなければならない. したがって,それほどパワーは必要ないまでも,ある程度の CPU リソースを割かなければならない. また,従来的なファイルシステムでは,データ領域のサイズは最初にディスクを初期化するときに決めなければならず,後から容量を増加させることはしばしば困難である (ZFS などのファイルシステムを使えばある程度は自由にファイルシステムのサイズを変更することは可能である). よって,従来的なクラウドでは,ストレージを借りる際にはあらかじめディスクのサイズを指定せねばならず,ディスクの中身が空であろうと満杯であろうと,同じ利用料金が発生することになる (figure_title).

    Simple Storage Service (S3) は,サーバーレスなストレージシステムを提供する (figure_title). S3 は従来的なストレージシステムと異なり, OS に"マウントする”という概念はない. 基本的に API を通じてデータの読み書きの操作が行われる. また,データの冗長化や暗号化,バックアップの作成など,通常ならば OS と CPU が介在しなければならない操作も, API を通じて行うことができる. S3 では事前に決められたディスク領域のサイズはなく,データを入れれば入れた分だけ,保存領域は拡大していく (仕様上はペタバイトスケールのデータを保存することが可能である). ストレージにかかる料金は,保存してあるデータの総容量で決定される.

    S3 と従来的なファイルシステムの比較

    S3 を利用する際に,料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 説明のため主要な事項のみ取り出している. 詳細は 公式ドキュメンテーション "Amazon S3 pricing" を参照).

    S3 の利用料金
    項目料金

    Data storage (First 50TB)

    $0.023 per GB per month

    PUT, COPY, POST, LIST requests (per 1,000 requests)

    $0.005

    GET, SELECT, and all other requests (per 1,000 requests)

    $0.0004

    Data Transfer IN To Amazon S3 From Internet

    $0

    Data Transfer OUT From Amazon S3 To Internet

    $0.09 per GB

    第一に,データの保存には $0.025 per GB のコストが月ごとに発生する. したがって,1000GB のデータを S3 に一ヵ月保存した場合, $25 の料金が発生することになる. また,PUT, COPY, POST などのリクエスト (=データを書き込む操作) に対しては,データ容量に関係なく,1000 回ごとに $0.005 のコストが発生する. GET, SELECT などのリクエスト (=データを読み込む操作) に対しては,1000 回ごとに $0.0004 のコストが発生する. また, S3 はデータを外に取り出す際の通信にもコストが生じる. 執筆時点では,S3 からインターネットを通じて外部にデータを転送 (data-out) すると $0.09 per GB のコストが発生する. データをインターネットを通じて S3 に入れる (data-in) 通信は無料で行える. また, AWS の 同じ Region 内のサービス (Lambda や EC2 など) にデータを転送するのは無料である. AWS のリージョンをまたいだデータの転送にはコストが発生する. いずれにせよ,サーバーレスの概念に則り,すべての料金が従量課金制で決定される設定になっている.

    サーバーレスデータベース: DynamoDB

    サーバーレスの概念は,データベースにも適用することができる.

    ここでいうデータベースとは, Web サービスなどにおけるユーザーや商品の情報を記録しておくための保存領域のことを指している. 従来的に有名なデータベースとしては MySQL, PostgreSQL, MongoDB などが挙げられる. データベースと普通のストレージの違いは,データの検索機能にある. 普通のストレージではデータは単純にディスクに書き込まれるだけだが, データベースでは検索がより効率的になるようなデータの配置がされたり, 頻繁にアクセスされるデータはメモリーにキャッシュされるなどの機能が備わっている. これにより,巨大なデータの中から,興味のある要素を高速に取得することができる.

    このような検索機能を実現するには,当然 CPU の存在が必須である. したがって,従来的なデータベースを構築する際は,ストレージ領域に加えて,たくさんの CPU コアを搭載したマシンが用いられることが多い. また,データベースが巨大な場合は複数マシンにまたがった分散型のシステムが設計される. 分散型システムの場合は, Serverful クラウド (従来型) で議論したようにデータベースへのアクセス負荷に応じて適切なスケーリングがなされる必要がある.

    DynamoDB は, AWS が提供しているサーバーレスな分散型データベースである. サーバーレスであるので,占有されたデータベース用仮想インスタンスは存在せず, API を通じてデータの書き込み・読み出し・検索などの操作を行う. S3 と同様に,データ保存領域の上限は定められておらず,データを入れれば入れた分だけ,保存領域は拡大していく. また,データベースへの負荷が増減したときのスケーリングは, DynamoDB が自動で行うので,ユーザーは心配する必要はない.

    DynamoDB での利用料金の計算はやや複雑なのだが, "On-demand Capacity" というモードで使用した場合の料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 詳細は 公式ドキュメンテーション "Pricing for On-Demand Capacity" を参照).

    DynamoDB の利用料金
    項目料金

    Write request units

    $1.25 per million write request units

    Read request units

    $0.25 per million read request units

    Data storage

    $0.25 per GB-month

    DynamoDB ではデータの書き込み操作の単位を write request unit とよび,データの読み込み操作の単位を read request unit とよぶ. 基本的に, 1kB 以下のデータを一度書き込むと 1 write request unit を消費し,4kB 以下のデータを一度読み込むと 1 read request unit を消費する (詳しくは 公式ドキュメンテーション "Read/Write Capacity Mode" を参照のこと). write request units は 100 万回ごとに $1.25, read request units は 100 万回ごとに $0.25 のコストが設定されている. また,保存されたデータ容量に対して $0.25 per GB のコストが月ごとに発生する. DynamoDB は高速な検索機能などを備えたデータベースであるので, GB あたりのストレージコストは S3 に比べ 10 倍程度高い. DynamoDB のデータの転送に関わるコストは,同じリージョン内ならば data-in,data-out ともに $0 である. リージョンをまたいだ通信には別途コストが発生する.

    その他のサーバーレスクラウドの構成要素

    以上で紹介した Lambda, S3, DynamoDB がサーバーレスクラウドの中で最も使用する頻度が高いサービスになる. その他のサーバーレスクラウドの構成要素を以下に列挙する. いくつかについては,今後のハンズオンを行う中で改めて解説を行う.

    • API Gateway: API を構築する際のルーティングを担う. (#sec_bashoutter) で取り上げる.

    • Fargate: (#sec_fargate_qabot) で触れた Fargate も,サーバーレスクラウドの要素の一部である. Lambda との違いは,Lambda よりも大容量のメモリーや CPU を要するような計算などを行うことができる点が挙げられる.

    • Simple Notification Service (SNS): サーバーレスのサービス間でイベントをやり取りするためのサービス.

    • Step Functions: サーバーレスのサービス間のオーケストレーションを担う.

    サーバーレスアーキテクチャは万能か?

    この問いへの答えは,筆者は NO であると考える.

    ここまで,サーバーレスの利点を強調して説明をしてきたが,まだまだ新しい技術なだけに,欠点,あるいはサーバーフルなシステムに劣る点は数多くある.

    大きな欠点を一つあげるとすれば,サーバーレスのシステムは各クラウドプラットフォームに固有なものなので,特定のプラットフォームでしか運用できないシステムになってしまう点であろう. AWS で作成したサーバーレスのシステムを, Google のクラウドに移植するには,かなり大掛かりなプログラムの書き換えが必要になる. 一方, serverful なシステムであれば,プラットフォーム間のマイグレーションは比較的簡単に行うことができる. クラウドプロバイダーとしては,自社のシステムへの依存度を強めることで,顧客を離さないようにするという狙いがあるのだろう…

    その他,サーバーレスコンピューティングの欠点や今後の課題などは,次の論文で詳しく議論されている. 興味のある読者はぜひ読んでいただきたい.

    ',55);function f(_,S,v,y,q,P){const a=t;return l(),i("div",null,[u,c(a,{readTime:"9",words:"2.4k"}),b])}const L=d(g,[["render",f]]);export{A as __pageData,L as default}; diff --git a/assets/development_aws_serverless.md.715b8a8d.lean.js b/assets/development_aws_serverless.md.a89d6134.lean.js similarity index 93% rename from assets/development_aws_serverless.md.715b8a8d.lean.js rename to assets/development_aws_serverless.md.a89d6134.lean.js index 7d8f2856..10bac951 100644 --- a/assets/development_aws_serverless.md.715b8a8d.lean.js +++ b/assets/development_aws_serverless.md.a89d6134.lean.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,a as o,b as s,c as n,d as p}from"./chunks/s3_vs_filesystem.fd65005d.js";import{_ as d,o as l,c as i,H as c,k as e,a as m,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const A=JSON.parse('{"title":"Serverless architecture","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/serverless.md","filePath":"development/aws/serverless.md","lastUpdated":1695377563000}'),g={name:"development/aws/serverless.md"},u=e("h1",{id:"serverless-architecture",tabindex:"-1"},[m("Serverless architecture "),e("a",{class:"header-anchor",href:"#serverless-architecture","aria-label":'Permalink to "Serverless architecture"'},"​")],-1),b=h("",55);function f(_,S,v,y,q,P){const a=t;return l(),i("div",null,[u,c(a,{readTime:"9",words:"2.4k"}),b])}const L=d(g,[["render",f]]);export{A as __pageData,L as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as r,a as o,b as s,c as n,d as p}from"./chunks/s3_vs_filesystem.fd65005d.js";import{_ as d,o as l,c as i,H as c,k as e,a as m,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const A=JSON.parse('{"title":"Serverless architecture","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/serverless.md","filePath":"development/aws/serverless.md","lastUpdated":1699051935000}'),g={name:"development/aws/serverless.md"},u=e("h1",{id:"serverless-architecture",tabindex:"-1"},[m("Serverless architecture "),e("a",{class:"header-anchor",href:"#serverless-architecture","aria-label":'Permalink to "Serverless architecture"'},"​")],-1),b=h("",55);function f(_,S,v,y,q,P){const a=t;return l(),i("div",null,[u,c(a,{readTime:"9",words:"2.4k"}),b])}const L=d(g,[["render",f]]);export{A as __pageData,L as default}; diff --git a/assets/development_aws_webserver.md.441ce29f.js b/assets/development_aws_webserver.md.89157904.js similarity index 99% rename from assets/development_aws_webserver.md.441ce29f.js rename to assets/development_aws_webserver.md.89157904.js index bed8dd09..878b2245 100644 --- a/assets/development_aws_webserver.md.441ce29f.js +++ b/assets/development_aws_webserver.md.89157904.js @@ -1 +1 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as d,a as r}from"./chunks/rest_api.602a6e96.js";import{_ as a,o as s,c,H as p,k as t,a as i,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Web サービスの作り方","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/webserver.md","filePath":"development/aws/webserver.md","lastUpdated":1695377563000}'),l={name:"development/aws/webserver.md"},T=t("h1",{id:"web-サービスの作り方",tabindex:"-1"},[i("Web サービスの作り方 "),t("a",{class:"header-anchor",href:"#web-サービスの作り方","aria-label":'Permalink to "Web サービスの作り方"'},"​")],-1),P=n('

    ここからが,本書第三部の内容になる. これまでのセクションでは,仮想サーバーをクラウド上に起動し,そこで計算を走らせる方法について解説をしてきた. EC2, ECS, Fargate, Batch などを利用して,動的にスケールするクラスターを構成し,並列にタスクを実行するクラウドシステムを実装してきた. 振り返ると,これまで紹介してきた内容は,自分自身が行いたい計算をクラウドを駆使することで実現する,という用途にフォーカスしていたことに気がつくだろう. 一方で,広く一般の人々に使ってもらえるような計算サービス・データベースを提供する,というのもクラウドの重要な役割として挙げられる.

    本章から始まる第三部では,前回までとは少し方向性を変え,どのようにしてクラウド上にアプリケーションを展開し,広く一般の人に使ってもらうか,という点を講義したいと思う. これを通じて,どのようにして世の中のウェブサービスができ上がっているのかを知り,さらにどうやって自分でそのようなアプリケーションをゼロから構築するのか,という点を学んでもらう. その過程で,サーバーレスアーキテクチャという最新のクラウド設計手法を解説する.

    その前準備として,本章ではどのようにしてウェブサービスが出来上がっているのか,その背後にある技術の概要を解説する. 用語の解説が中心となるが,後のハンズオンを実装するために必須の知識であるので,理解して前に進むよう心がけよう.

    ウェブサービスの仕組み  — Twitter を例に

    あなたがパソコンやスマートフォンから Twitter, Facebook, YouTube などのウェブサービスにアクセスしたとき,実際にどのようなことが行われ,コンテンツが提示されているのだろうか?

    HTTP を通じたサーバーとクライアントのデータのやり取りは,すでに知っている読者も多いだろうし,逆にすべて解説しようとすると紙面が足りないので,ここではエッセンスの説明のみにとどめる. 以降では Twitter を具体例として,背後にあるサーバーとクライアントの間の通信を概説しよう. 概念図としては figure_title のような通信がクライアントとサーバーの間で行われていることになる.

    クライアントと Web サーバーの通信の概念図

    前提として,クライアントとサーバーの通信は HTTP (Hypertext Transfer Protocol) を使って行われる. また,最近では,暗号化された HTTP である HTTPS (HTTPS (Hypertext Transfer Protocol Secure)) を用いることがスタンダードになってきている. 第一のステップとして,クライアントは HTTP(S) 通信によってサーバーから静的なコンテンツを取得する. 静的なコンテンツとは, HTML (Hyptertext Markup Language) で記述されたウェブページの文書本体, CSS (Cascading Style Sheets) で記述されたページのデザインやレイアウトファイル,そして JavaScript (JS) で記述されたページの動的な挙動を定義したプログラム,が含まれる. Twitter を含む現代的なウェブアプリケーションの設計では,この静的なファイル群はページの”枠”を定義するだけで,中身となるコンテンツ (例: ツイートの一覧) は別途 API (Application Programming Interface) によって取得されなければならない. そこで,クライアントは先のステップで取得された JavaScript で定義されたプログラムに従って,サーバーに API を送信し,ツイートや画像データを取得する. この際,テキストデータのやり取りには JSON (JavaScript Object Notation) というフォーマットが用いられることが多い. 画像や動画などのコンテンツも同様に API により取得される. このようにして取得されたテキストや画像が,HTML の文書に埋め込まれることで,最終的にユーザーに提示されるページが完成するのである. また,新しいツイートを投稿するときにも,クライアントから API を通じてサーバーのデータベースにデータが書き込まれる.

    REST API

    API (Application Programming Interface) とはこれまで何度も出てきた言葉であるが,ここではよりフォーマルな定義付けを行う. API とはあるソフトウェア・アプリケーションが,外部のソフトウェアに対してコマンドやデータをやり取りするための媒介の一般的総称である. とくに,ウェブサービスの文脈では,サーバーが外界に対して提示しているコマンドの一覧のことを意味する. クライアントは,提示されている API から適切なコマンドを使うことによって,所望のデータを取得したり,あるいはサーバーにデータを送信したりする.

    とくに,ウェブの文脈では REST (Representational State Transfer) とよばれる設計思想に基づいた API が現在では最も一般的に使われている. REST の設計指針に従った API のことを REST API あるいは RESTful API とよんだりする.

    REST API は, figure_title に示したような MethodURI (Universal Resource Identifier) の組からなる.

    REST API

    Method (メソッド) とは,どのような操作を行いたいかを抽象的に表す,"動詞" として捉えることができる. メソッドには HTTP 規格で定義された 9 個の動詞 (verb) を使用することができる. この中でも, GET, POST, PUT, PATCH, DELETE の 5 個が最も頻繁に使用される (table_title). この 5 つのメソッドによる操作を総称して CRUD (create, read, update, and delete) とよぶ.

    REST API Methods
    メソッド意図される動作

    GET

    要素を取得する

    POST

    新しい要素を作成する

    PUT

    既存の要素を新しい要素と置き換える

    PATCH

    既存の要素の一部を更新する

    DELETE

    要素を削除する

    一方, URI は操作が行われる対象,すなわち "目的語" を表す. ウェブの文脈では操作が行われる対象のことをしばしば リソース とよぶ. URI は多くの場合 http または https から始まるウェブサーバーのアドレスから始まり, / (スラッシュ) 以降に所望のリソースのパスが指定される. figure_title の例で言えば, https://api.twitter.com というアドレスの /1.1/status/home_timeline というリソースを取得 (GET) せよ,という意味になる (なお,ここで 1.1 という数字は API のバージョンを示している). この API リクエストによって,ユーザーのホームのタイムラインのツイートの一覧が取得される.

    REST API のメソッドには, table_title で挙げたもの以外に, HTTP プロトコルで定義されているほかのメソッド (OPTIONS, TRACE など) を用いることもできるが,あまり一般的ではない.

    また,これらのメソッドだけでは動詞として表現しきれないこともあるが, URI の名前でより意味を明確にすることもある. メソッドの使い方も,要素を削除する際は必ず DELETE を使わなければならない,という決まりもなく,たとえば, Twitter API でツイートを消す API は POST statuses/destroy/:id で定義されている. 最終的には,各ウェブサービスが公開している API ドキュメンテーションを読んで,それぞれの API がどんな操作をするのかを調べる必要がある.

    REST の概念は 2000 年代初頭に確立され,今日の API 設計のスタンダードとなった. 一方で,ウェブのテクノロジーが進歩するにつれて,新たな API の設計アプローチの需要も高まっている. 近年とくに人気を集めているのが, GraphQL と呼ばれる API の設計方法である. GraphQL は Facebook 社によって最初に作られ,現在は GraghQL Foundation によって維持と更新がされている. GraphQL を使用すると,クライアントは REST と比較してより柔軟性の高いデータのクエリを行うことができるなど,いくつかの利点がある. キーワードだけでも知っておくと,今後役に立つだろう.

    Twitter API

    もう少し具体的にウェブサービスの API を体験する目的で,ここでは Twitter の API を見てみよう. Twitter が提供している API の一覧は Twitter の Developer Documentation で見ることができる. いくつかの代表的な API を table_title にまとめた.

    Twitter API
    エンドポイント動作

    GET statuses/home_timeline

    ホームのタイムラインのツイートの一覧を取得する.

    GET statuses/show/:id

    :id で指定されたツイートの詳細情報を取得する.

    GET search

    ツイートの検索を実行する.

    POST statuses/update

    新しいツイートを投稿する.

    POST media/upload

    画像をアップロードする

    POST statuses/destroy/:id

    :id で指定されたツイートを削除する.

    POST statuses/retweet/:id

    :id で指定されたツイートをリツイートする.

    POST statuses/unretweet/:id

    :id で指定されたツイートのリツイートを取り消す.

    POST favorites/create

    選択したツイートを"いいね"する.

    POST favorites/destroy

    選択したツイートを"いいね"を取り消す.

    この API リストをもとに, Twitter のアプリまたはウェブサイトを開いたときに起こるクライアントとサーバーの通信をシミュレートしてみよう.

    ユーザーが Twitter を開くと,まず最初に GET statuses/home_timeline の API リクエストによって,ユーザーのホームのタイムラインのツイートのリストが取得される. 個々のツイートは JSON 形式のデータになっており, id, text, user, coordinates, entities などの属性を含む. id はツイートに固有な ID を表し, text はツイートの本文を含んでいる. user はツイートを投稿したユーザーの名前やプロフィール画像の URL などを含んだ JSON データになっている. coordinates にはツイートが発信された地理的な座標が記録されている. また, entities にはツイートに関連するメディアファイル (画像など) のリンクなどの情報が埋め込まれている. GET statuses/home_timeline からは直近のツイートのリスト (リストが長すぎる場合は途中で切られたもの) が取得される. もしツイートの ID を知っている場合は GET statuses/show/:id を呼ぶことによって, :id パラメータで指定された特定のツイートを取得することができる.

    ツイートの検索を行うためには GET search API を使用する. この API には,ツイートに含まれる単語や,ハッシュタグ,ツイートの発信された日時や場所など,様々なクエリの条件を渡すことができる. API からは, GET statuses/home_timeline などと同様, JSON 形式のツイートのデータが返される.

    ユーザーが新しいツイートを投稿するには POST statuses/update のエンドポイントを利用する. POST statuses/update には,ツイートの文章や,リプライの場合はリプライ先のツイートの ID などのデータを送信する. また,ツイートに画像データを添付したい場合は, POST media/upload を併せて使用する. ツイートの削除を行うには, POST statuses/destroy/:id を用いる.

    そのほか,頻繁に行われる操作としては, POST statuses/retweet/:idPOST statuses/unretweet/:id がある. これらは, :id で指定されるツイートに対して,それぞれリツイートを実行あるいは取り消すための API である. また, POST favorites/createPOST favorites/destroy を使用することによって,選択されたツイートに"いいね"を追加したり,取り消したりする操作を行う.

    このような一連の操作が, Twitter のアプリの背後では行われている. また,自分自身でボットを作成したい場合は,これらの API を適切に組み合わせ,カスタムのプログラムを書くことで実現される.

    このように, API はあらゆるウェブサービスを作るうえで一番基礎となる要素である. 次からの章では本章で紹介した用語が何度も出てくるので,頭の片隅に置いたうえで読み進めていただきたい.

    ',29);function h(u,g,_,I,S,m){const e=o;return s(),c("div",null,[T,p(e,{readTime:"5",words:"1.4k"}),P])}const v=a(l,[["render",h]]);export{E as __pageData,v as default}; +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as d,a as r}from"./chunks/rest_api.602a6e96.js";import{_ as a,o as s,c,H as p,k as t,a as i,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Web サービスの作り方","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/webserver.md","filePath":"development/aws/webserver.md","lastUpdated":1699051935000}'),l={name:"development/aws/webserver.md"},T=t("h1",{id:"web-サービスの作り方",tabindex:"-1"},[i("Web サービスの作り方 "),t("a",{class:"header-anchor",href:"#web-サービスの作り方","aria-label":'Permalink to "Web サービスの作り方"'},"​")],-1),P=n('

    ここからが,本書第三部の内容になる. これまでのセクションでは,仮想サーバーをクラウド上に起動し,そこで計算を走らせる方法について解説をしてきた. EC2, ECS, Fargate, Batch などを利用して,動的にスケールするクラスターを構成し,並列にタスクを実行するクラウドシステムを実装してきた. 振り返ると,これまで紹介してきた内容は,自分自身が行いたい計算をクラウドを駆使することで実現する,という用途にフォーカスしていたことに気がつくだろう. 一方で,広く一般の人々に使ってもらえるような計算サービス・データベースを提供する,というのもクラウドの重要な役割として挙げられる.

    本章から始まる第三部では,前回までとは少し方向性を変え,どのようにしてクラウド上にアプリケーションを展開し,広く一般の人に使ってもらうか,という点を講義したいと思う. これを通じて,どのようにして世の中のウェブサービスができ上がっているのかを知り,さらにどうやって自分でそのようなアプリケーションをゼロから構築するのか,という点を学んでもらう. その過程で,サーバーレスアーキテクチャという最新のクラウド設計手法を解説する.

    その前準備として,本章ではどのようにしてウェブサービスが出来上がっているのか,その背後にある技術の概要を解説する. 用語の解説が中心となるが,後のハンズオンを実装するために必須の知識であるので,理解して前に進むよう心がけよう.

    ウェブサービスの仕組み  — Twitter を例に

    あなたがパソコンやスマートフォンから Twitter, Facebook, YouTube などのウェブサービスにアクセスしたとき,実際にどのようなことが行われ,コンテンツが提示されているのだろうか?

    HTTP を通じたサーバーとクライアントのデータのやり取りは,すでに知っている読者も多いだろうし,逆にすべて解説しようとすると紙面が足りないので,ここではエッセンスの説明のみにとどめる. 以降では Twitter を具体例として,背後にあるサーバーとクライアントの間の通信を概説しよう. 概念図としては figure_title のような通信がクライアントとサーバーの間で行われていることになる.

    クライアントと Web サーバーの通信の概念図

    前提として,クライアントとサーバーの通信は HTTP (Hypertext Transfer Protocol) を使って行われる. また,最近では,暗号化された HTTP である HTTPS (HTTPS (Hypertext Transfer Protocol Secure)) を用いることがスタンダードになってきている. 第一のステップとして,クライアントは HTTP(S) 通信によってサーバーから静的なコンテンツを取得する. 静的なコンテンツとは, HTML (Hyptertext Markup Language) で記述されたウェブページの文書本体, CSS (Cascading Style Sheets) で記述されたページのデザインやレイアウトファイル,そして JavaScript (JS) で記述されたページの動的な挙動を定義したプログラム,が含まれる. Twitter を含む現代的なウェブアプリケーションの設計では,この静的なファイル群はページの”枠”を定義するだけで,中身となるコンテンツ (例: ツイートの一覧) は別途 API (Application Programming Interface) によって取得されなければならない. そこで,クライアントは先のステップで取得された JavaScript で定義されたプログラムに従って,サーバーに API を送信し,ツイートや画像データを取得する. この際,テキストデータのやり取りには JSON (JavaScript Object Notation) というフォーマットが用いられることが多い. 画像や動画などのコンテンツも同様に API により取得される. このようにして取得されたテキストや画像が,HTML の文書に埋め込まれることで,最終的にユーザーに提示されるページが完成するのである. また,新しいツイートを投稿するときにも,クライアントから API を通じてサーバーのデータベースにデータが書き込まれる.

    REST API

    API (Application Programming Interface) とはこれまで何度も出てきた言葉であるが,ここではよりフォーマルな定義付けを行う. API とはあるソフトウェア・アプリケーションが,外部のソフトウェアに対してコマンドやデータをやり取りするための媒介の一般的総称である. とくに,ウェブサービスの文脈では,サーバーが外界に対して提示しているコマンドの一覧のことを意味する. クライアントは,提示されている API から適切なコマンドを使うことによって,所望のデータを取得したり,あるいはサーバーにデータを送信したりする.

    とくに,ウェブの文脈では REST (Representational State Transfer) とよばれる設計思想に基づいた API が現在では最も一般的に使われている. REST の設計指針に従った API のことを REST API あるいは RESTful API とよんだりする.

    REST API は, figure_title に示したような MethodURI (Universal Resource Identifier) の組からなる.

    REST API

    Method (メソッド) とは,どのような操作を行いたいかを抽象的に表す,"動詞" として捉えることができる. メソッドには HTTP 規格で定義された 9 個の動詞 (verb) を使用することができる. この中でも, GET, POST, PUT, PATCH, DELETE の 5 個が最も頻繁に使用される (table_title). この 5 つのメソッドによる操作を総称して CRUD (create, read, update, and delete) とよぶ.

    REST API Methods
    メソッド意図される動作

    GET

    要素を取得する

    POST

    新しい要素を作成する

    PUT

    既存の要素を新しい要素と置き換える

    PATCH

    既存の要素の一部を更新する

    DELETE

    要素を削除する

    一方, URI は操作が行われる対象,すなわち "目的語" を表す. ウェブの文脈では操作が行われる対象のことをしばしば リソース とよぶ. URI は多くの場合 http または https から始まるウェブサーバーのアドレスから始まり, / (スラッシュ) 以降に所望のリソースのパスが指定される. figure_title の例で言えば, https://api.twitter.com というアドレスの /1.1/status/home_timeline というリソースを取得 (GET) せよ,という意味になる (なお,ここで 1.1 という数字は API のバージョンを示している). この API リクエストによって,ユーザーのホームのタイムラインのツイートの一覧が取得される.

    REST API のメソッドには, table_title で挙げたもの以外に, HTTP プロトコルで定義されているほかのメソッド (OPTIONS, TRACE など) を用いることもできるが,あまり一般的ではない.

    また,これらのメソッドだけでは動詞として表現しきれないこともあるが, URI の名前でより意味を明確にすることもある. メソッドの使い方も,要素を削除する際は必ず DELETE を使わなければならない,という決まりもなく,たとえば, Twitter API でツイートを消す API は POST statuses/destroy/:id で定義されている. 最終的には,各ウェブサービスが公開している API ドキュメンテーションを読んで,それぞれの API がどんな操作をするのかを調べる必要がある.

    REST の概念は 2000 年代初頭に確立され,今日の API 設計のスタンダードとなった. 一方で,ウェブのテクノロジーが進歩するにつれて,新たな API の設計アプローチの需要も高まっている. 近年とくに人気を集めているのが, GraphQL と呼ばれる API の設計方法である. GraphQL は Facebook 社によって最初に作られ,現在は GraghQL Foundation によって維持と更新がされている. GraphQL を使用すると,クライアントは REST と比較してより柔軟性の高いデータのクエリを行うことができるなど,いくつかの利点がある. キーワードだけでも知っておくと,今後役に立つだろう.

    Twitter API

    もう少し具体的にウェブサービスの API を体験する目的で,ここでは Twitter の API を見てみよう. Twitter が提供している API の一覧は Twitter の Developer Documentation で見ることができる. いくつかの代表的な API を table_title にまとめた.

    Twitter API
    エンドポイント動作

    GET statuses/home_timeline

    ホームのタイムラインのツイートの一覧を取得する.

    GET statuses/show/:id

    :id で指定されたツイートの詳細情報を取得する.

    GET search

    ツイートの検索を実行する.

    POST statuses/update

    新しいツイートを投稿する.

    POST media/upload

    画像をアップロードする

    POST statuses/destroy/:id

    :id で指定されたツイートを削除する.

    POST statuses/retweet/:id

    :id で指定されたツイートをリツイートする.

    POST statuses/unretweet/:id

    :id で指定されたツイートのリツイートを取り消す.

    POST favorites/create

    選択したツイートを"いいね"する.

    POST favorites/destroy

    選択したツイートを"いいね"を取り消す.

    この API リストをもとに, Twitter のアプリまたはウェブサイトを開いたときに起こるクライアントとサーバーの通信をシミュレートしてみよう.

    ユーザーが Twitter を開くと,まず最初に GET statuses/home_timeline の API リクエストによって,ユーザーのホームのタイムラインのツイートのリストが取得される. 個々のツイートは JSON 形式のデータになっており, id, text, user, coordinates, entities などの属性を含む. id はツイートに固有な ID を表し, text はツイートの本文を含んでいる. user はツイートを投稿したユーザーの名前やプロフィール画像の URL などを含んだ JSON データになっている. coordinates にはツイートが発信された地理的な座標が記録されている. また, entities にはツイートに関連するメディアファイル (画像など) のリンクなどの情報が埋め込まれている. GET statuses/home_timeline からは直近のツイートのリスト (リストが長すぎる場合は途中で切られたもの) が取得される. もしツイートの ID を知っている場合は GET statuses/show/:id を呼ぶことによって, :id パラメータで指定された特定のツイートを取得することができる.

    ツイートの検索を行うためには GET search API を使用する. この API には,ツイートに含まれる単語や,ハッシュタグ,ツイートの発信された日時や場所など,様々なクエリの条件を渡すことができる. API からは, GET statuses/home_timeline などと同様, JSON 形式のツイートのデータが返される.

    ユーザーが新しいツイートを投稿するには POST statuses/update のエンドポイントを利用する. POST statuses/update には,ツイートの文章や,リプライの場合はリプライ先のツイートの ID などのデータを送信する. また,ツイートに画像データを添付したい場合は, POST media/upload を併せて使用する. ツイートの削除を行うには, POST statuses/destroy/:id を用いる.

    そのほか,頻繁に行われる操作としては, POST statuses/retweet/:idPOST statuses/unretweet/:id がある. これらは, :id で指定されるツイートに対して,それぞれリツイートを実行あるいは取り消すための API である. また, POST favorites/createPOST favorites/destroy を使用することによって,選択されたツイートに"いいね"を追加したり,取り消したりする操作を行う.

    このような一連の操作が, Twitter のアプリの背後では行われている. また,自分自身でボットを作成したい場合は,これらの API を適切に組み合わせ,カスタムのプログラムを書くことで実現される.

    このように, API はあらゆるウェブサービスを作るうえで一番基礎となる要素である. 次からの章では本章で紹介した用語が何度も出てくるので,頭の片隅に置いたうえで読み進めていただきたい.

    ',29);function h(u,g,_,I,S,m){const e=o;return s(),c("div",null,[T,p(e,{readTime:"5",words:"1.4k"}),P])}const v=a(l,[["render",h]]);export{E as __pageData,v as default}; diff --git a/assets/development_aws_webserver.md.441ce29f.lean.js b/assets/development_aws_webserver.md.89157904.lean.js similarity index 93% rename from assets/development_aws_webserver.md.441ce29f.lean.js rename to assets/development_aws_webserver.md.89157904.lean.js index 180bbc5a..8aecae37 100644 --- a/assets/development_aws_webserver.md.441ce29f.lean.js +++ b/assets/development_aws_webserver.md.89157904.lean.js @@ -1 +1 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as d,a as r}from"./chunks/rest_api.602a6e96.js";import{_ as a,o as s,c,H as p,k as t,a as i,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Web サービスの作り方","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/webserver.md","filePath":"development/aws/webserver.md","lastUpdated":1695377563000}'),l={name:"development/aws/webserver.md"},T=t("h1",{id:"web-サービスの作り方",tabindex:"-1"},[i("Web サービスの作り方 "),t("a",{class:"header-anchor",href:"#web-サービスの作り方","aria-label":'Permalink to "Web サービスの作り方"'},"​")],-1),P=n("",29);function h(u,g,_,I,S,m){const e=o;return s(),c("div",null,[T,p(e,{readTime:"5",words:"1.4k"}),P])}const v=a(l,[["render",h]]);export{E as __pageData,v as default}; +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as d,a as r}from"./chunks/rest_api.602a6e96.js";import{_ as a,o as s,c,H as p,k as t,a as i,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Web サービスの作り方","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/webserver.md","filePath":"development/aws/webserver.md","lastUpdated":1699051935000}'),l={name:"development/aws/webserver.md"},T=t("h1",{id:"web-サービスの作り方",tabindex:"-1"},[i("Web サービスの作り方 "),t("a",{class:"header-anchor",href:"#web-サービスの作り方","aria-label":'Permalink to "Web サービスの作り方"'},"​")],-1),P=n("",29);function h(u,g,_,I,S,m){const e=o;return s(),c("div",null,[T,p(e,{readTime:"5",words:"1.4k"}),P])}const v=a(l,[["render",h]]);export{E as __pageData,v as default}; diff --git a/assets/development_file-naming-convention.md.ff928233.js b/assets/development_file-naming-convention.md.0fb858f4.js similarity index 57% rename from assets/development_file-naming-convention.md.ff928233.js rename to assets/development_file-naming-convention.md.0fb858f4.js index 183b5fad..8c2d32eb 100644 --- a/assets/development_file-naming-convention.md.ff928233.js +++ b/assets/development_file-naming-convention.md.0fb858f4.js @@ -1,67 +1,67 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as i,c as l,H as o,k as e,a as r,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const j=JSON.parse('{"title":"File Name Conventions","description":"","frontmatter":{},"headers":[],"relativePath":"development/file-naming-convention.md","filePath":"development/file-naming-convention.md","lastUpdated":1695377563000}'),p={name:"development/file-naming-convention.md"},c=e("h1",{id:"file-name-conventions",tabindex:"-1"},[r("File Name Conventions "),e("a",{class:"header-anchor",href:"#file-name-conventions","aria-label":'Permalink to "File Name Conventions"'},"​")],-1),d=t(`

    A collection of guidelines for writing file names used in web projects.

    Possible characters

    Use dashes as delimiters

    • You should use dashes (-) as delimiters.
    • Periods are allowed in some cases, such as for languages and conditions.
    • Never use spaces or underscores. Spaces are converted to %20 in URLs or can break an URL when shared. Underscores are difficult to see when the file name is displayed as an underlined link. Although the use of underscores does not impact your ranking that much, Google advices not to use underscores.
    • Exceptions apply for functional requirements, such as for Sass partials. A leading underscore informs the Sass compiler a file is only a partial file and should never be generated into a stand alone CSS file.

    Right:

    file-name-with-dashes.en.min.html
    file-name-with-dashes.en.min.html

    Do not use special characters

    Avoid using non-alphanumeric characters in file names, such as: '*' ':' '\\' '/' '<' '>' '|' '"' '!' '?' '[' ']' ';' '=' '+' '&' '£' '$' '' '%' or ','. These characters can have special meaning in programming languages or can cause problems with different operating systems.

    Use lowercase, never uppercase

    We should always consider URLs as case-sensitive according to W3.org. Therefore, use lowercase to reduces errors when typing URLs.

    Write sections of a file name in a consistent order

    Sections should be written in this order:

    1. Description
    2. Number
    3. Date
    4. Target device, image size, pixel density
    5. Version number
    6. Status
    7. Language code
    8. File conditions

    Possible combinations

    description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
    -description.min.js
    -description.en.html
    -description-01.jpg
    -description-02.jpg
    -description-1024x768_2x.jpg
    -description-desk_2x.jpg
    description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
    -description.min.js
    -description.en.html
    -description-01.jpg
    -description-02.jpg
    -description-1024x768_2x.jpg
    -description-desk_2x.jpg

    Write description for developers and users

    Don't be afraid to write long informative file names. Few people type a file name manually and most operating systems support 255 characters. But only add information that makes it easy for users and developers to recognize files from one another at a glance. For the description use information such as:

    • type of data
    • project name or acronym
    • subjects
    • people's names
    • characteristics
    • location

    Give your images detailed, informative filenames The filename can give Google clues about the subject matter of the image. Try to make your filename a good description of the subject matter of the image. For example, my-new-black-kitten.jpg is a lot more informative than IMG00023.JPG. Descriptive filenames can also be useful to users: If we're unable to find suitable text in the page on which we found the image, we'll use the filename as the image's snippet in our search results. - Google, 2015, Image publishing guidelines

    Keep people's names compact

    Sometimes you want to include the name of a person in the file name, e.g. the author or the person in the photo.

    • Write names without word delimiters.
    • Only write initials for the first name and write the last name in full. There are two exceptions: (1) when the last name or final file name is very long you may use initials for the last name; (2) when there is already a person with the same combination, you may write the first name in full.
    • If people have exactly the same name written in full, you can add a number: firstnamelastname2.

    Right:

    bvandebiezen.jpg
    -shoogenhout.jpg
    -a-very-long-description-with-name-bvdb.jpg
    -asmith.jpg
    -adamsmith.jpg
    -adamsmith2.jpg
    bvandebiezen.jpg
    -shoogenhout.jpg
    -a-very-long-description-with-name-bvdb.jpg
    -asmith.jpg
    -adamsmith.jpg
    -adamsmith2.jpg

    Use two or more digits to distinguish sequential files with the same description

    • Start number with a dash as a delimiter.
    • Add a zero to single digit numbers, e.g. '01' instead of '1'.
    • Numbers may also be placed before the description if needed. A dash will still be used as delimiter with the description.

    Right:

    description-01.jpg
    -description-02.jpg
    -description-03.jpg
    -description-04.jpg
    -
    -01-description.jpg
    -02-description.jpg
    -03-description.jpg
    -04-description.jpg
    description-01.jpg
    -description-02.jpg
    -description-03.jpg
    -description-04.jpg
    -
    -01-description.jpg
    -02-description.jpg
    -03-description.jpg
    -04-description.jpg

    Keep dates or date ranges compact and start with year

    • Write dates without delimiters.
    • Always use four digits for years, two digits for months and two digits for days.
    • Start with year, then month, and end with day if available: yyyymmdd, yyyymm, or yyyy. This makes sure similar file names are sorted by date when sorted alphabetically.
    • Use a double dash to separate two dates describing an interval: yyyy--yyyy. Start with the earliest date.

    Right:

    description-20150401.php
    -description-201504.php
    -description-2015.php
    -description-2000--2010.php
    description-20150401.php
    -description-201504.php
    -description-2015.php
    -description-2000--2010.php

    See 'ISO 8601' for further reading.

    Use special modifiers for target devices, image sizes or media queries, and pixel densities.

    Modifiers are inspired by Apple iOS naming conventions. There are some differences. Apple uses '@'as a delimiter for the section indicating higher resolution images, for example '@2x' for retina images. Because '@' is a reserved character and can create problems, we use Bourbon's convention: an underscore. Also, Apple uses a tilde (~) as a delimiter for a section indicating specific devices. Because also a tilde can create problems, we suggest to simply use a dash.

    • Order should be: (1) target device or media query, (2) size, (3) pixel density.
    • Start target device or media queries with a dash (-) as delimiter.
    • Start image sizes with a dash (-) as delimiter.
    • Start pixel density with an underscore (_) as delimiter, for example '_2x' or '_3x'.
    • When only a width or height is available or applicable, add a 'w' for width or 'h' for height directly after the the amount of pixels.
    • When both measurements are available, do not add a 'w' or 'h' and separate the width and height with an 'x'.
    • When both the width and height should not exceed a dimension but the images should keep the original aspect ratio, add a 'max' (maximum) after the amount of pixels.

    Right:

    description_2x.jpg
    -description-lap.jpg
    -description-desk.jpg
    -description-lap_2x.jpg
    -description-palm-1024w_2x.jpg
    -description-iphone5-568h_2x.jpg
    -description-palm-1024x768_2x.jpg
    -description-40max.jpg
    description_2x.jpg
    -description-lap.jpg
    -description-desk.jpg
    -description-lap_2x.jpg
    -description-palm-1024w_2x.jpg
    -description-iphone5-568h_2x.jpg
    -description-palm-1024x768_2x.jpg
    -description-40max.jpg

    Use version numbers if available

    • Start version with a dash (-) as delimiter.
    • Use periods (.) to separate point releases.
    • Always add trailing zeros to major releases, e.g. '2.0' instead of '2'.
    • Types, such as 'a' (alpha), 'b' (beta), 'rc1' (release candidate 1) can be added without delimiters.

    Right:

    description-0.5.js
    -description-1.0b.js
    -description-1.0rc1.js
    description-0.5.js
    -description-1.0b.js
    -description-1.0rc1.js

    Add status when needed

    • You can optionally add a file status such as 'draft' and 'published'.
    • Start status with a dash.

    Right:

    description-draft.md
    description-draft.md

    Add language code only when different languages are available

    • Use a period to separate the language code from the rest of the file name.
    • Use ISO 639-1, two-letter codes, for languages.
    • Only add languages when different languages are available.

    Right:

    description.nl.txt
    -description.en.txt
    description.nl.txt
    -description.en.txt

    Add file conditions just before the file extension

    • The file condition should be the last part, just before the file extension.
    • Use a period (.) to separate the condition from the rest of the file name.
    • Use periods (.) as a delimiter for different conditions.

    Right:

    description.min.js
    -description.custom1234.min.js
    description.min.js
    -description.custom1234.min.js

    Rewrite original file names not following conventions

    It is not preferred to keep file names in it's original format if it doesn't match your file name conventions. But in some cases it is easier to keep the file name untouched. Sometimes you want to easily replace a file with a newer one from the original source in the future.

    `,56);function h(m,u,g,b,f,y){const s=a;return i(),l("div",null,[c,o(s,{readTime:"7",words:"1.2k"}),d])}const x=n(p,[["render",h]]);export{j as __pageData,x as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as i,c as l,H as o,k as e,a as t,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const j=JSON.parse('{"title":"File Name Conventions","description":"","frontmatter":{},"headers":[],"relativePath":"development/file-naming-convention.md","filePath":"development/file-naming-convention.md","lastUpdated":1699051935000}'),p={name:"development/file-naming-convention.md"},c=e("h1",{id:"file-name-conventions",tabindex:"-1"},[t("File Name Conventions "),e("a",{class:"header-anchor",href:"#file-name-conventions","aria-label":'Permalink to "File Name Conventions"'},"​")],-1),d=r(`

    A collection of guidelines for writing file names used in web projects.

    Possible characters

    Use dashes as delimiters

    • You should use dashes (-) as delimiters.
    • Periods are allowed in some cases, such as for languages and conditions.
    • Never use spaces or underscores. Spaces are converted to %20 in URLs or can break an URL when shared. Underscores are difficult to see when the file name is displayed as an underlined link. Although the use of underscores does not impact your ranking that much, Google advices not to use underscores.
    • Exceptions apply for functional requirements, such as for Sass partials. A leading underscore informs the Sass compiler a file is only a partial file and should never be generated into a stand alone CSS file.

    Right:

    file-name-with-dashes.en.min.html
    file-name-with-dashes.en.min.html

    Do not use special characters

    Avoid using non-alphanumeric characters in file names, such as: '*' ':' '\\' '/' '<' '>' '|' '"' '!' '?' '[' ']' ';' '=' '+' '&' '£' '$' '' '%' or ','. These characters can have special meaning in programming languages or can cause problems with different operating systems.

    Use lowercase, never uppercase

    We should always consider URLs as case-sensitive according to W3.org. Therefore, use lowercase to reduces errors when typing URLs.

    Write sections of a file name in a consistent order

    Sections should be written in this order:

    1. Description
    2. Number
    3. Date
    4. Target device, image size, pixel density
    5. Version number
    6. Status
    7. Language code
    8. File conditions

    Possible combinations

    description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
    +description.min.js
    +description.en.html
    +description-01.jpg
    +description-02.jpg
    +description-1024x768_2x.jpg
    +description-desk_2x.jpg
    description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
    +description.min.js
    +description.en.html
    +description-01.jpg
    +description-02.jpg
    +description-1024x768_2x.jpg
    +description-desk_2x.jpg

    Write description for developers and users

    Don't be afraid to write long informative file names. Few people type a file name manually and most operating systems support 255 characters. But only add information that makes it easy for users and developers to recognize files from one another at a glance. For the description use information such as:

    • type of data
    • project name or acronym
    • subjects
    • people's names
    • characteristics
    • location

    Give your images detailed, informative filenames The filename can give Google clues about the subject matter of the image. Try to make your filename a good description of the subject matter of the image. For example, my-new-black-kitten.jpg is a lot more informative than IMG00023.JPG. Descriptive filenames can also be useful to users: If we're unable to find suitable text in the page on which we found the image, we'll use the filename as the image's snippet in our search results. - Google, 2015, Image publishing guidelines

    Keep people's names compact

    Sometimes you want to include the name of a person in the file name, e.g. the author or the person in the photo.

    • Write names without word delimiters.
    • Only write initials for the first name and write the last name in full. There are two exceptions: (1) when the last name or final file name is very long you may use initials for the last name; (2) when there is already a person with the same combination, you may write the first name in full.
    • If people have exactly the same name written in full, you can add a number: firstnamelastname2.

    Right:

    bvandebiezen.jpg
    +shoogenhout.jpg
    +a-very-long-description-with-name-bvdb.jpg
    +asmith.jpg
    +adamsmith.jpg
    +adamsmith2.jpg
    bvandebiezen.jpg
    +shoogenhout.jpg
    +a-very-long-description-with-name-bvdb.jpg
    +asmith.jpg
    +adamsmith.jpg
    +adamsmith2.jpg

    Use two or more digits to distinguish sequential files with the same description

    • Start number with a dash as a delimiter.
    • Add a zero to single digit numbers, e.g. '01' instead of '1'.
    • Numbers may also be placed before the description if needed. A dash will still be used as delimiter with the description.

    Right:

    description-01.jpg
    +description-02.jpg
    +description-03.jpg
    +description-04.jpg
    +
    +01-description.jpg
    +02-description.jpg
    +03-description.jpg
    +04-description.jpg
    description-01.jpg
    +description-02.jpg
    +description-03.jpg
    +description-04.jpg
    +
    +01-description.jpg
    +02-description.jpg
    +03-description.jpg
    +04-description.jpg

    Keep dates or date ranges compact and start with year

    • Write dates without delimiters.
    • Always use four digits for years, two digits for months and two digits for days.
    • Start with year, then month, and end with day if available: yyyymmdd, yyyymm, or yyyy. This makes sure similar file names are sorted by date when sorted alphabetically.
    • Use a double dash to separate two dates describing an interval: yyyy--yyyy. Start with the earliest date.

    Right:

    description-20150401.php
    +description-201504.php
    +description-2015.php
    +description-2000--2010.php
    description-20150401.php
    +description-201504.php
    +description-2015.php
    +description-2000--2010.php

    See 'ISO 8601' for further reading.

    Use special modifiers for target devices, image sizes or media queries, and pixel densities.

    Modifiers are inspired by Apple iOS naming conventions. There are some differences. Apple uses '@'as a delimiter for the section indicating higher resolution images, for example '@2x' for retina images. Because '@' is a reserved character and can create problems, we use Bourbon's convention: an underscore. Also, Apple uses a tilde (~) as a delimiter for a section indicating specific devices. Because also a tilde can create problems, we suggest to simply use a dash.

    • Order should be: (1) target device or media query, (2) size, (3) pixel density.
    • Start target device or media queries with a dash (-) as delimiter.
    • Start image sizes with a dash (-) as delimiter.
    • Start pixel density with an underscore (_) as delimiter, for example '_2x' or '_3x'.
    • When only a width or height is available or applicable, add a 'w' for width or 'h' for height directly after the the amount of pixels.
    • When both measurements are available, do not add a 'w' or 'h' and separate the width and height with an 'x'.
    • When both the width and height should not exceed a dimension but the images should keep the original aspect ratio, add a 'max' (maximum) after the amount of pixels.

    Right:

    description_2x.jpg
    +description-lap.jpg
    +description-desk.jpg
    +description-lap_2x.jpg
    +description-palm-1024w_2x.jpg
    +description-iphone5-568h_2x.jpg
    +description-palm-1024x768_2x.jpg
    +description-40max.jpg
    description_2x.jpg
    +description-lap.jpg
    +description-desk.jpg
    +description-lap_2x.jpg
    +description-palm-1024w_2x.jpg
    +description-iphone5-568h_2x.jpg
    +description-palm-1024x768_2x.jpg
    +description-40max.jpg

    Use version numbers if available

    • Start version with a dash (-) as delimiter.
    • Use periods (.) to separate point releases.
    • Always add trailing zeros to major releases, e.g. '2.0' instead of '2'.
    • Types, such as 'a' (alpha), 'b' (beta), 'rc1' (release candidate 1) can be added without delimiters.

    Right:

    description-0.5.js
    +description-1.0b.js
    +description-1.0rc1.js
    description-0.5.js
    +description-1.0b.js
    +description-1.0rc1.js

    Add status when needed

    • You can optionally add a file status such as 'draft' and 'published'.
    • Start status with a dash.

    Right:

    description-draft.md
    description-draft.md

    Add language code only when different languages are available

    • Use a period to separate the language code from the rest of the file name.
    • Use ISO 639-1, two-letter codes, for languages.
    • Only add languages when different languages are available.

    Right:

    description.nl.txt
    +description.en.txt
    description.nl.txt
    +description.en.txt

    Add file conditions just before the file extension

    • The file condition should be the last part, just before the file extension.
    • Use a period (.) to separate the condition from the rest of the file name.
    • Use periods (.) as a delimiter for different conditions.

    Right:

    description.min.js
    +description.custom1234.min.js
    description.min.js
    +description.custom1234.min.js

    Rewrite original file names not following conventions

    It is not preferred to keep file names in it's original format if it doesn't match your file name conventions. But in some cases it is easier to keep the file name untouched. Sometimes you want to easily replace a file with a newer one from the original source in the future.

    `,56);function h(m,u,b,g,f,y){const s=a;return i(),l("div",null,[c,o(s,{readTime:"7",words:"1.2k"}),d])}const x=n(p,[["render",h]]);export{j as __pageData,x as default}; diff --git a/assets/development_file-naming-convention.md.ff928233.lean.js b/assets/development_file-naming-convention.md.0fb858f4.lean.js similarity index 64% rename from assets/development_file-naming-convention.md.ff928233.lean.js rename to assets/development_file-naming-convention.md.0fb858f4.lean.js index dba2351a..50a8e4fe 100644 --- a/assets/development_file-naming-convention.md.ff928233.lean.js +++ b/assets/development_file-naming-convention.md.0fb858f4.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as i,c as l,H as o,k as e,a as r,Q as t}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const j=JSON.parse('{"title":"File Name Conventions","description":"","frontmatter":{},"headers":[],"relativePath":"development/file-naming-convention.md","filePath":"development/file-naming-convention.md","lastUpdated":1695377563000}'),p={name:"development/file-naming-convention.md"},c=e("h1",{id:"file-name-conventions",tabindex:"-1"},[r("File Name Conventions "),e("a",{class:"header-anchor",href:"#file-name-conventions","aria-label":'Permalink to "File Name Conventions"'},"​")],-1),d=t("",56);function h(m,u,g,b,f,y){const s=a;return i(),l("div",null,[c,o(s,{readTime:"7",words:"1.2k"}),d])}const x=n(p,[["render",h]]);export{j as __pageData,x as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as i,c as l,H as o,k as e,a as t,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const j=JSON.parse('{"title":"File Name Conventions","description":"","frontmatter":{},"headers":[],"relativePath":"development/file-naming-convention.md","filePath":"development/file-naming-convention.md","lastUpdated":1699051935000}'),p={name:"development/file-naming-convention.md"},c=e("h1",{id:"file-name-conventions",tabindex:"-1"},[t("File Name Conventions "),e("a",{class:"header-anchor",href:"#file-name-conventions","aria-label":'Permalink to "File Name Conventions"'},"​")],-1),d=r("",56);function h(m,u,b,g,f,y){const s=a;return i(),l("div",null,[c,o(s,{readTime:"7",words:"1.2k"}),d])}const x=n(p,[["render",h]]);export{j as __pageData,x as default}; diff --git a/assets/development_proxy4shell-terminal.md.a93dc7e4.js b/assets/development_proxy4shell-terminal.md.a93dc7e4.js new file mode 100644 index 00000000..fff6d0a1 --- /dev/null +++ b/assets/development_proxy4shell-terminal.md.a93dc7e4.js @@ -0,0 +1,79 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as l,c as p,H as r,a as e,k as s,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const i="/assets/2023-11-04-03-15-12.77ab4cd9.png",c="/assets/2023-11-02-04-44-14.08b67c2b.png",h="/assets/2023-11-04-00-42-58.d7bf77fb.png",d="/assets/2023-11-04-01-32-28.da2149a9.png",y="/assets/2023-11-04-03-49-38.78c93d29.png",u="/assets/2023-11-04-04-27-59.3d817820.png",m="/assets/2023-11-04-05-01-04.fd5f8fb7.png",q=JSON.parse('{"title":"Proxies Configuration for Shells & Terminal","description":"","frontmatter":{"title":"Proxies Configuration for Shells & Terminal","author":"Anda Toshiki","date":"2023-11-02T00:00:00.000Z"},"headers":[],"relativePath":"development/proxy4shell-terminal.md","filePath":"development/proxy4shell-terminal.md","lastUpdated":1699051935000}'),f={name:"development/proxy4shell-terminal.md"},b=s("h1",{id:"proxies-configuration-for-shells-terminal",tabindex:"-1"},[e("Proxies Configuration for Shells & Terminal "),s("a",{class:"header-anchor",href:"#proxies-configuration-for-shells-terminal","aria-label":'Permalink to "Proxies Configuration for Shells & Terminal"'},"​")],-1),g=n('

    TL;DR

    This article discusses the configuration of proxies for shells and terminals. It explains the advantages of using proxy servers to bypass network restrictions and surveillance. The article provides examples of the challenges faced when accessing foreign services and shows how to set up a proxy tunnel using the curl command. It also provides scripts and instructions for setting up proxy switches in different shell environments, such as zsh, bash, and Windows CMD and PowerShell. The article concludes with additional information on proxy configurations for applications like ssh and tips for working with authentication procedures.

    1. Background

    Proxies or namely proxy servers are by far one of the most affordable or cost-effective option to establish a masked layer connection to bypass the network restrictions with the annoying surveillance tracked by a local network ISP as compared to a click-to-use VPN service, which generically requires more individual invest to protect themselves under the insecure internet environment nowadays. When a user resides within the environment where the local gateways of full, user-dominant open access towards the internet is censored or restricted with domestic network blockages by the country.

    ',5),v=n('

    2. The Major Issue

    The majority of the issue still heavily preserves across the developmental fields which the layer of the blockage imposes limits on communicating with third-party, remote platforms such as Github or registries like NPM for frontend developments that stores key packages or components, as a requirement during a pre-built phase of a project. Most of the time foreign services becomes completely inaccessible or fortunately users could reach the services during a possible ISP maintenance downtime but normally the potentiality is mere, or hardly none yet the load speed before TTL connection expires are objectively slow, shortly before the origin site DNS being spoofed again. The unpleasant experiences with the networking somewhat affects interest on development reduces by high percentages or it even strand some awesome projects ran ashore ultimately.

    The following screenshots are a more direct representation to visualize the differences between the connection towards one of the most beloved search engine, Google with the following command via curl.

    sh
    curl -I google.com
    curl -I google.com

    The command is used to fetch the headers of a URL or web page. When you run "curl -I" followed by a URL, the command sends an HTTP HEAD request to the specified URL and retrieves the HTTP headers of the response. This allows you to view the information contained in the response headers without requesting and downloading the entire content of the page. The headers typically include details like the server information, content type, content length, status codes, and more.

    The following screenshot from terminal indicates the the final output of the package availability received without losses on a bare unmasked network environment, which returns FAIL in the final connection after a dry run fails 11s after when the TTL expires the connection fails.

    The next screenshot from terminal indicates a temporary proxy tunnel is established both in http and https protocol tunneled through a local proxy gateway at the local systemic IP address at 127.0.0.1 and exposes the proxy server at a mix of socks/https/http protocol port at 7890, just simply with the traditional export method by setting up in the nonce, the command is given as followed.

    sh
    export http_proxy=http://127.0.0.1:7890
    +export https_proxy=$http_proxy
    export http_proxy=http://127.0.0.1:7890
    +export https_proxy=$http_proxy

    And then we re-enter the same command with curl from above; surprisingly, the header responses returned TTP/1.1 200 OK, thus the conclusion drawn here is the proxy server we launched was successfully up and running with tunneled access towards foreign sites without restrictions! Hooray!

    ◎ Curl in action with successful response header from Google

    Since each proxy configuration might varies atop of the user preferred client, not including ShadowRocket, Clash, V2ray or other proprietary softwares that are licensed either behind a paywall to run with; or simply expensive to purchase a subscription; the proxy ports forwarded varies alongside the changes amongst clients. But the overall approach taken into the account still remains the same with the following traditional formats, the local IP of the machine (normally 127.0.0.1) followed after with the specified ports. In the scenario of the article is referenced as example, I chose Clash (in spite the entire Clash project repository as well as its affiliated forked projects are being taken down by anonymous reasons by either archiving the overall projects or simply shutting down due to possible legal actions or political reasons regarding the country of residency of various developers).

    shj
    # http protocal
    +http://127.0.0.1:7890
    +# https protocal
    +https://127.0.0.1:7890
    # http protocal
    +http://127.0.0.1:7890
    +# https protocal
    +https://127.0.0.1:7890

    2.1: Kill the Complexities; Unleash the Simplicity!

    But, the logic routes to the central question on: How can we simplify the course of action on setting up proxies without manually run export command every single time we wish to use? Below is a simple approach by aliasing a shortcut code to a proxy switch script amended towards your shell configuration profile that initializes on every session startups, in this case I uses zsh since it's integrated as the default shell on macOS since the release of macOS Catalina, yet it's one of my most familiar and favored shell when was using other OS as well.

    Though some people might use autosuggestion extensions as third-party shell features to automatically predict the command completion after a code piece is inputted such as zsh-autosuggestion plugin or fan of fish shell users has the native privilege of auto completions but I personally not fond of such featured integration since it might decelerate the load speed of an active session; I prefer stick tightly with original shell.

    sh
    # open your shell profile with an preferred editor
    +$ vim ~/.zshrc
    +
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +
    +# restart your terminal with a new session or reload the config
    +$ source ~/.zshrc
    # open your shell profile with an preferred editor
    +$ vim ~/.zshrc
    +
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +
    +# restart your terminal with a new session or reload the config
    +$ source ~/.zshrc

    The proxy essentially provides two shortcut command function defined with proxy_on and proxy_off. he proxy_on function sets the environment variables http_proxy and https_proxy to http://127.0.0.1:7890, which is the default proxy port of the traditional clash protocol, here is where you could replace the IP with other remote proxy servers or ports of other local proxies .Enabling a global proxy for the current terminal session. Meanwhile the proxy_off function unsets (removes) the http_proxy and https_proxy environment variables, effectively turning off the global proxy for the current terminal session. When any of the both executed, the indicator message will be echoed on the terminal, see the following screenshot in action.

    ◎ Enabling the shell session proxy with script

    After you reload your shell profile you can test out the scripted command yourself. To test whether the proxy has a successful setup after the proxy has been switched on, run echo $http_proxy or https_proxy with a dollar sign in front of the alias as an indicator for environmental variable, the third command as shown in the screenshot above, the command will simply print the configured variable value addressed to the specified alias. Contrarily, if your terminal returns the following resultant,

    sh
    $ proxy_on
    +zsh: command not found: proxy_on
    $ proxy_on
    +zsh: command not found: proxy_on

    Then you will have to distinguish the exact shell you are currently on, the hereinafter content are mainly targeted towards novice learners whom are unable to track the shell types or configuration on particular operating systems. The configuration file for each shell varies their file names as well the location of storage; while Mac users could directly apply changes based on the instruction provided above if your system if Catalina or above. To know what exactly the active shell running, run,

    sh
    $ echo $SHELL
    $ echo $SHELL

    The returned string text will be the name of the current active shell, the following is a list of the possible shell profile config name affiliated with each shell; most of the config profile files should be lied under the ~ or the root/home folder of each operating system with a dot in front of the file names are inferred as hidden file or directory in most of the Unix-like systems, such as macOS, Ubuntu, Debian and etc, but some of the config file such as fish shell could locate in an isolated config directory. The usual format of a config file is as followed,

    shell
    ~/.zshrc
    ~/.zshrc

    The following is a list of the most common shells with their possible profile file names that corresponded,

    • /bin/bash : .bash_profile or .bashrc
    • /bin/zsh : .zprofile or .zshrc
    • /bin/fish: ~/.config/fish/config

    Still, the location might still varies, users might have to perform individual research to precisely locate their configuration file location, which is out of my jurisdiction of concerns (it's just evident action of procrastination and laziness, my apologies if none of the ones above fits your demand) ;).

    For Unix-like users, after you have specified your shell as well as your config file name and locations, copy the following code chunk as command and paste it back into your terminal and run to apply permanent changes to the configuration.

    sh
    cat >> ~/.zshrc << EOF
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +EOF
    cat >> ~/.zshrc << EOF
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +EOF

    The script above will write-in and install the proxy switch script and save the the content to the very end of the file. As a kindly reminder, if your shell is not zsh make sure to replace the string after cat >> to the actual path of your profile as well as your proxy server IP and port to the actual functioning details to your own demand; then ultimately, don't for get to reinitialize the shell by close and reopen the terminal or simply sourcing the config,

    sh
    source ~/.zshrc
    source ~/.zshrc

    To check whether the proxy script has taken its effect to the current session, don't forget to rerun the same echo command indicated as above. And up until here, the script has been properly installed and operatable as a charm, if your's still does not take any effect, go through the process again and read carefully through the documentation.

    3: To All Windows Users

    The documentation above are mainly targeted towards macOS & Linux users, to setup local proxy with Windows machines there is a complete different approach if you are more comfortably working with Powershells and CMD, since I disused windows less and less frequently by the time I decided to upgrade my device to macOS; even if I did use Windows my primary choice of developmental environment is still Linux by the native support of WSL with enhanced Ubuntu version in a virtual environment; the following commands are only done from my prior researches, I do not fully guarantee the usability of the commands, please use them at your own risks if any unexpected errors not only including system crashes or other affiliated damages, I do not relate responsibility to any of those presented.

    Simple concluding, abandon proprietary software, fall in the hug of open source; Linux even if most of the users might feel overwhelming when getting started with the system first :). Alright, enough with off-topic talkings, let's jump right in the process.

    3.1: CMD

    cmd
    set http_proxy=http://127.0.0.1:7890
    +set https_proxy=http://127.0.0.1:7890
    set http_proxy=http://127.0.0.1:7890
    +set https_proxy=http://127.0.0.1:7890

    The commands are basically the same to Unix but the major difference is the amend commands in Windows are set instead of export. Once again I haven't personally tested the command, thus only use them as a reference. And whenever you wish to unset the global proxy for the session just simply run the set proxy command again but without any proxy server details.

    cmd
    set http_proxy=
    +set https_proxy=
    set http_proxy=
    +set https_proxy=

    3.2: PowerShell

    Alike CMD, the string after are exactly the same but the setup prefix command differentiates,

    powershell
    $env:http_proxy="http://127.0.0.1:1080"
    +$env:https_proxy="http://127.0.0.1:1080"
    $env:http_proxy="http://127.0.0.1:1080"
    +$env:https_proxy="http://127.0.0.1:1080"

    And to revert to the default proxy setting, execute the following command to unset both the http and https proxy.

    powershell
    $env:http_proxy=""
    +$env:https_proxy=""
    $env:http_proxy=""
    +$env:https_proxy=""

    4: Extended Trivia on Proxy

    Sometimes a proxy server may require an authentication procedure involving passcode for accessing before establishing a secure connection to interact with the server itself. From the partial article above we only discussed on a simple local proxy server setup including a host IP with its forwarded port gateways; but when facing the scenario described for a net connection, we will need a bit more complex method when working in the CLI environment.

    Before we start, quoting from one of the answer from AskUbuntu, resolving the misconception on the difference between terminal application and the net utilities falls underly,

    Terminal is not net application. Maybe is better to say, in your case, terminal is container for net application like ssh, telnet, lftp, wget, lynx ...

    A terminal provides a command-line interface that allows users to send commands and receive responses from network applications, facilitating communication and control over a network connection. It acts as a mediator between the user and the network applications, enabling the user to send instructions and receive information, but not a proxy client.

    Done with the technical talkings, now let's dive into the actual configuration process of the shell. Other than simply inputting a host IP and a port followed, the following formats are the default configuration for a proxy server with HTTP connection protocol, follow the exact same process as described based on your shell type, modify the fields with the following,

    shell
    export http_proxy=http://username:password@proxyhost:port/
    +export ftp_proxy=http://username:password@proxyhost:port/
    +export telnet_proxy=http://username:password@proxyhost:port/
    export http_proxy=http://username:password@proxyhost:port/
    +export ftp_proxy=http://username:password@proxyhost:port/
    +export telnet_proxy=http://username:password@proxyhost:port/

    Another approach suggested by the same user whom provided the answer on AskUbuntu for all Ubuntu users, edit the proxy configuration at the root of your machine as follows,

    sh
    sudo -H vim /etc/profile.d/proxy.sh
    sudo -H vim /etc/profile.d/proxy.sh

    And add the exported proxy members aligning the format as above, then save and reinitialize the environment, viola. The patches edited are mainly targeted for incorporating with wget, ftp, lftp, telnet in terminal.

    When working with ssh instance over a proxy, a different approach has to be taken since SSH library does not natively support SOCKS5 client, user will have to pass a ProxyCommand option as a workaround to apply proxied connection, below is an instance of socat,

    sh
    ssh -o ProxyCommand='socat - SOCKS4A:myproxy:%h:%p,socksuser=nobody' user@host
    ssh -o ProxyCommand='socat - SOCKS4A:myproxy:%h:%p,socksuser=nobody' user@host

    The proxyCommand option allows user to integrate socat as an intermediary mediator to establish connection above a proxy. Other alternatives like tsocks are as well viable to transparently use SOCKS for TCP traffic, Exemplifying running SOCKS5 over socat2,

    bash
    ssh -o ProxyCommand='socat - "SOCKS5:%h:%p|tcp:myproxy:1080"' user@host
    ssh -o ProxyCommand='socat - "SOCKS5:%h:%p|tcp:myproxy:1080"' user@host

    Further, socat2 for HTTP Proxy CONNECT method,

    bash
    ssh -o ProxyCommand='socat - "PROXY:%h:%p|tcp:myproxy:80"' user@host
    ssh -o ProxyCommand='socat - "PROXY:%h:%p|tcp:myproxy:80"' user@host
    `,65);function w(F,x,C,A,D,k){const a=o;return l(),p("div",null,[b,r(a,{readTime:"17",words:"2.8k"}),g,e(" while I adopt absolute subjective yet objective perspectives on the individual viewpoints towards the MIIT department of each country those of which applies the internet regulatory services within the national range for avoiding pitfalls on misleading information brought by cross-border influences; meanwhile regardlessly such measures are still facing controversial debates amongst publics that vastly limits the independent freedom rights, though advantages must not be underestimated, still. "),v])}const T=t(f,[["render",w]]);export{q as __pageData,T as default}; diff --git a/assets/development_proxy4shell-terminal.md.a93dc7e4.lean.js b/assets/development_proxy4shell-terminal.md.a93dc7e4.lean.js new file mode 100644 index 00000000..6901c473 --- /dev/null +++ b/assets/development_proxy4shell-terminal.md.a93dc7e4.lean.js @@ -0,0 +1 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as t,o as l,c as p,H as r,a as e,k as s,Q as n}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const i="/assets/2023-11-04-03-15-12.77ab4cd9.png",c="/assets/2023-11-02-04-44-14.08b67c2b.png",h="/assets/2023-11-04-00-42-58.d7bf77fb.png",d="/assets/2023-11-04-01-32-28.da2149a9.png",y="/assets/2023-11-04-03-49-38.78c93d29.png",u="/assets/2023-11-04-04-27-59.3d817820.png",m="/assets/2023-11-04-05-01-04.fd5f8fb7.png",q=JSON.parse('{"title":"Proxies Configuration for Shells & Terminal","description":"","frontmatter":{"title":"Proxies Configuration for Shells & Terminal","author":"Anda Toshiki","date":"2023-11-02T00:00:00.000Z"},"headers":[],"relativePath":"development/proxy4shell-terminal.md","filePath":"development/proxy4shell-terminal.md","lastUpdated":1699051935000}'),f={name:"development/proxy4shell-terminal.md"},b=s("h1",{id:"proxies-configuration-for-shells-terminal",tabindex:"-1"},[e("Proxies Configuration for Shells & Terminal "),s("a",{class:"header-anchor",href:"#proxies-configuration-for-shells-terminal","aria-label":'Permalink to "Proxies Configuration for Shells & Terminal"'},"​")],-1),g=n("",5),v=n("",65);function w(F,x,C,A,D,k){const a=o;return l(),p("div",null,[b,r(a,{readTime:"17",words:"2.8k"}),g,e(" while I adopt absolute subjective yet objective perspectives on the individual viewpoints towards the MIIT department of each country those of which applies the internet regulatory services within the national range for avoiding pitfalls on misleading information brought by cross-border influences; meanwhile regardlessly such measures are still facing controversial debates amongst publics that vastly limits the independent freedom rights, though advantages must not be underestimated, still. "),v])}const T=t(f,[["render",w]]);export{q as __pageData,T as default}; diff --git a/assets/development_rclone-for-r2.md.65c0da34.js b/assets/development_rclone-for-r2.md.65c0da34.js new file mode 100644 index 00000000..4d141687 --- /dev/null +++ b/assets/development_rclone-for-r2.md.65c0da34.js @@ -0,0 +1,55 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as o,H as p,k as s,a as r,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Configure rclone for R2","description":"","frontmatter":{},"headers":[],"relativePath":"development/rclone-for-r2.md","filePath":"development/rclone-for-r2.md","lastUpdated":1699051935000}'),t={name:"development/rclone-for-r2.md"},i=s("h1",{id:"configure-rclone-for-r2",tabindex:"-1"},[r("Configure rclone for R2 "),s("a",{class:"header-anchor",href:"#configure-rclone-for-r2","aria-label":'Permalink to "Configure rclone for R2"'},"​")],-1),y=c(`

    Example of how to configure rclone to use R2.

    You must generate an Access Key before getting started. All examples will utilize access_key_id and access_key_secret variables which represent the Access Key ID and Secret Access Key values you generated.

    With rclone installed, you may run rclone config to configure a new S3 storage provider. You will be prompted with a series of questions for the new prvider details.

    If you have already configured rclone in the past, you may run rclone config file to print the location of your rclone configuration file:

    bash
    $ rclone config file
    +# Configuration file is stored at:
    +# ~/.config/rclone/rclone.conf
    $ rclone config file
    +# Configuration file is stored at:
    +# ~/.config/rclone/rclone.conf

    Then use an editor (nano or vim, for example) to add or edit the new provider. This example assumes you are adding a new r2demo provider:

    bash
    [r2]
    +type = s3
    +provider = Cloudflare
    +access_key_id = abc123 # Your access_key_id
    +secret_access_key = xyz456 # Your access_key_secret
    +endpoint = https://<accountid>.r2.cloudflarestorage.com
    +acl = private
    [r2]
    +type = s3
    +provider = Cloudflare
    +access_key_id = abc123 # Your access_key_id
    +secret_access_key = xyz456 # Your access_key_secret
    +endpoint = https://<accountid>.r2.cloudflarestorage.com
    +acl = private

    You may then use the new rclone provider for any of your normal workflows.

    List buckets & objects

    The rclone tree command can be used to list the contents of the remote, in this case Cloudflare R2.

    bash
    $ rclone tree r2demo:
    +# /
    +# ├── user-uploads
    +# │   └── foobar.png
    +# └── my-bucket-name
    +#     ├── cat.png
    +#     └── todos.txt
    +
    +$ rclone tree r2demo:my-bucket-name
    +# /
    +# ├── cat.png
    +# └── todos.txt
    $ rclone tree r2demo:
    +# /
    +# ├── user-uploads
    +# │   └── foobar.png
    +# └── my-bucket-name
    +#     ├── cat.png
    +#     └── todos.txt
    +
    +$ rclone tree r2demo:my-bucket-name
    +# /
    +# ├── cat.png
    +# └── todos.txt

    Upload and retrieve objects

    The rclone copy command can be used to upload objects to an R2 bucket and vice versa - this allows you to upload files up to the 5 TB maximum object size that R2 supports.

    bash
    # Upload dog.txt to the user-uploads bucket
    +$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    +$ rclone tree r2demo:user-uploads
    +# /
    +# ├── foobar.png
    +# └── dog.txt
    +
    +# Download dog.txt from the user-uploads bucket
    +$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    # Upload dog.txt to the user-uploads bucket
    +$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    +$ rclone tree r2demo:user-uploads
    +# /
    +# ├── foobar.png
    +# └── dog.txt
    +
    +# Download dog.txt from the user-uploads bucket
    +$ rclone copy r2demo:user-uploads/dog.txt dog.txt

    Generate presigned URLs

    You can also generate presigned links which allow you to share public access to a file temporarily using the rclone link command.

    `,16);function d(u,b,m,F,h,D){const n=a;return l(),o("div",null,[i,p(n,{readTime:"2",words:"336"}),y])}const _=e(t,[["render",d]]);export{C as __pageData,_ as default}; diff --git a/assets/development_rclone-for-r2.md.65c0da34.lean.js b/assets/development_rclone-for-r2.md.65c0da34.lean.js new file mode 100644 index 00000000..d02344b9 --- /dev/null +++ b/assets/development_rclone-for-r2.md.65c0da34.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as o,H as p,k as s,a as r,Q as c}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const C=JSON.parse('{"title":"Configure rclone for R2","description":"","frontmatter":{},"headers":[],"relativePath":"development/rclone-for-r2.md","filePath":"development/rclone-for-r2.md","lastUpdated":1699051935000}'),t={name:"development/rclone-for-r2.md"},i=s("h1",{id:"configure-rclone-for-r2",tabindex:"-1"},[r("Configure rclone for R2 "),s("a",{class:"header-anchor",href:"#configure-rclone-for-r2","aria-label":'Permalink to "Configure rclone for R2"'},"​")],-1),y=c("",16);function d(u,b,m,F,h,D){const n=a;return l(),o("div",null,[i,p(n,{readTime:"2",words:"336"}),y])}const _=e(t,[["render",d]]);export{C as __pageData,_ as default}; diff --git a/assets/development_rclone-for-r2.md.72ca2dcc.js b/assets/development_rclone-for-r2.md.72ca2dcc.js deleted file mode 100644 index eaf602ee..00000000 --- a/assets/development_rclone-for-r2.md.72ca2dcc.js +++ /dev/null @@ -1,55 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as o,H as p,k as s,a as t,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Configure rclone for R2","description":"","frontmatter":{},"headers":[],"relativePath":"development/rclone-for-r2.md","filePath":"development/rclone-for-r2.md","lastUpdated":1695377563000}'),c={name:"development/rclone-for-r2.md"},i=s("h1",{id:"configure-rclone-for-r2",tabindex:"-1"},[t("Configure rclone for R2 "),s("a",{class:"header-anchor",href:"#configure-rclone-for-r2","aria-label":'Permalink to "Configure rclone for R2"'},"​")],-1),y=r(`

    Example of how to configure rclone to use R2.

    You must generate an Access Key before getting started. All examples will utilize access_key_id and access_key_secret variables which represent the Access Key ID and Secret Access Key values you generated.

    With rclone installed, you may run rclone config to configure a new S3 storage provider. You will be prompted with a series of questions for the new prvider details.

    If you have already configured rclone in the past, you may run rclone config file to print the location of your rclone configuration file:

    bash
    $ rclone config file
    -# Configuration file is stored at:
    -# ~/.config/rclone/rclone.conf
    $ rclone config file
    -# Configuration file is stored at:
    -# ~/.config/rclone/rclone.conf

    Then use an editor (nano or vim, for example) to add or edit the new provider. This example assumes you are adding a new r2demo provider:

    bash
    [r2]
    -type = s3
    -provider = Cloudflare
    -access_key_id = abc123 # Your access_key_id
    -secret_access_key = xyz456 # Your access_key_secret
    -endpoint = https://<accountid>.r2.cloudflarestorage.com
    -acl = private
    [r2]
    -type = s3
    -provider = Cloudflare
    -access_key_id = abc123 # Your access_key_id
    -secret_access_key = xyz456 # Your access_key_secret
    -endpoint = https://<accountid>.r2.cloudflarestorage.com
    -acl = private

    You may then use the new rclone provider for any of your normal workflows.

    List buckets & objects

    The rclone tree command can be used to list the contents of the remote, in this case Cloudflare R2.

    bash
    $ rclone tree r2demo:
    -# /
    -# ├── user-uploads
    -# │   └── foobar.png
    -# └── my-bucket-name
    -#     ├── cat.png
    -#     └── todos.txt
    -
    -$ rclone tree r2demo:my-bucket-name
    -# /
    -# ├── cat.png
    -# └── todos.txt
    $ rclone tree r2demo:
    -# /
    -# ├── user-uploads
    -# │   └── foobar.png
    -# └── my-bucket-name
    -#     ├── cat.png
    -#     └── todos.txt
    -
    -$ rclone tree r2demo:my-bucket-name
    -# /
    -# ├── cat.png
    -# └── todos.txt

    Upload and retrieve objects

    The rclone copy command can be used to upload objects to an R2 bucket and vice versa - this allows you to upload files up to the 5 TB maximum object size that R2 supports.

    bash
    # Upload dog.txt to the user-uploads bucket
    -$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    -$ rclone tree r2demo:user-uploads
    -# /
    -# ├── foobar.png
    -# └── dog.txt
    -
    -# Download dog.txt from the user-uploads bucket
    -$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    # Upload dog.txt to the user-uploads bucket
    -$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    -$ rclone tree r2demo:user-uploads
    -# /
    -# ├── foobar.png
    -# └── dog.txt
    -
    -# Download dog.txt from the user-uploads bucket
    -$ rclone copy r2demo:user-uploads/dog.txt dog.txt

    Generate presigned URLs

    You can also generate presigned links which allow you to share public access to a file temporarily using the rclone link command.

    `,16);function d(A,u,b,m,f,h){const n=a;return l(),o("div",null,[i,p(n,{readTime:"2",words:"336"}),y])}const v=e(c,[["render",d]]);export{k as __pageData,v as default}; diff --git a/assets/development_rclone-for-r2.md.72ca2dcc.lean.js b/assets/development_rclone-for-r2.md.72ca2dcc.lean.js deleted file mode 100644 index c0d8b110..00000000 --- a/assets/development_rclone-for-r2.md.72ca2dcc.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as e,o as l,c as o,H as p,k as s,a as t,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Configure rclone for R2","description":"","frontmatter":{},"headers":[],"relativePath":"development/rclone-for-r2.md","filePath":"development/rclone-for-r2.md","lastUpdated":1695377563000}'),c={name:"development/rclone-for-r2.md"},i=s("h1",{id:"configure-rclone-for-r2",tabindex:"-1"},[t("Configure rclone for R2 "),s("a",{class:"header-anchor",href:"#configure-rclone-for-r2","aria-label":'Permalink to "Configure rclone for R2"'},"​")],-1),y=r("",16);function d(A,u,b,m,f,h){const n=a;return l(),o("div",null,[i,p(n,{readTime:"2",words:"336"}),y])}const v=e(c,[["render",d]]);export{k as __pageData,v as default}; diff --git a/assets/getting-started.md.54a05997.js b/assets/getting-started.md.54a05997.js deleted file mode 100644 index 24c872ad..00000000 --- a/assets/getting-started.md.54a05997.js +++ /dev/null @@ -1,11 +0,0 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as l,c as e,H as t,k as s,a as p,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Git push results in \\"Authentication Failed”","description":"","frontmatter":{"title":"Git push results in \\"Authentication Failed”","editLink":true,"lastUpdated":true},"headers":[],"relativePath":"getting-started.md","filePath":"getting-started.md","lastUpdated":1695377563000}'),c={name:"getting-started.md"},i=s("h1",{id:"git-push-results-in-authentication-failed",tabindex:"-1"},[p('Git push results in "Authentication Failed” '),s("a",{class:"header-anchor",href:"#git-push-results-in-authentication-failed","aria-label":'Permalink to "Git push results in "Authentication Failed”"'},"​")],-1),y=r(`

    Issue

    bash
    $ git push
    -Username for 'https://github.com': \${{ GITHUB_USERNAME }}
    -Password for 'https://andatoshiki@github.com': \${{ GITHUB_PASSWORD }} # or GitHub personal access token
    -remote: Invalid username or password.
    -fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
    $ git push
    -Username for 'https://github.com': \${{ GITHUB_USERNAME }}
    -Password for 'https://andatoshiki@github.com': \${{ GITHUB_PASSWORD }} # or GitHub personal access token
    -remote: Invalid username or password.
    -fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'

    git push to GitHub remote branch failed via https protocol

    Solution

    Solution 1

    If you enabled two-factor authentication in your GitHub account you won't be able to push via HTTPS using your accounts password. Instead you need to generate a personal access token. This can be done in the application settings of your GitHub account. Using this token as your password should allow you to push to your remote repository via HTTPS. Use your username as usual.

    You may also need to update the origin for your repository if it is set to HTTPS. Do this to switch to SSH:

    bash
    $ git remote -v
    -$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
    $ git remote -v
    -$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git

    Solution 2

    GitHub username & password/access token mismatched due to prior temporary Git config setup → Reset Git global username & email config or in current repository

    To set your global username/email configuration:

    1. Open the command line.
    2. Set your username: git config --global user.name "FIRST_NAME LAST_NAME"
    3. Set your email address: git config --global user.email "MY_NAME@example.com"

    To set repository-specific username/email configuration:

    1. From the command line, change into the repository directory.
    2. Set your username: git config user.name "FIRST_NAME LAST_NAME"
    3. Set your email address: git config user.email "MY_NAME@example.com"
    4. Verify your configuration by displaying your configuration file: cat .git/config
    `,14);function u(d,A,h,m,g,b){const a=o;return l(),e("div",null,[i,t(a,{readTime:"1",words:"271"}),y])}const k=n(c,[["render",u]]);export{S as __pageData,k as default}; diff --git a/assets/getting-started.md.975024a7.js b/assets/getting-started.md.975024a7.js new file mode 100644 index 00000000..6db68714 --- /dev/null +++ b/assets/getting-started.md.975024a7.js @@ -0,0 +1,11 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as l,H as t,k as s,a as p,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Git push results in \\"Authentication Failed”","description":"","frontmatter":{"title":"Git push results in \\"Authentication Failed”","editLink":true,"lastUpdated":true},"headers":[],"relativePath":"getting-started.md","filePath":"getting-started.md","lastUpdated":1699051935000}'),i={name:"getting-started.md"},c=s("h1",{id:"git-push-results-in-authentication-failed",tabindex:"-1"},[p('Git push results in "Authentication Failed” '),s("a",{class:"header-anchor",href:"#git-push-results-in-authentication-failed","aria-label":'Permalink to "Git push results in "Authentication Failed”"'},"​")],-1),y=r(`

    Issue

    bash
    $ git push
    +Username for 'https://github.com': \${{ GITHUB_USERNAME }}
    +Password for 'https://andatoshiki@github.com': \${{ GITHUB_PASSWORD }} # or GitHub personal access token
    +remote: Invalid username or password.
    +fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
    $ git push
    +Username for 'https://github.com': \${{ GITHUB_USERNAME }}
    +Password for 'https://andatoshiki@github.com': \${{ GITHUB_PASSWORD }} # or GitHub personal access token
    +remote: Invalid username or password.
    +fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'

    git push to GitHub remote branch failed via https protocol

    Solution

    Solution 1

    If you enabled two-factor authentication in your GitHub account you won't be able to push via HTTPS using your accounts password. Instead you need to generate a personal access token. This can be done in the application settings of your GitHub account. Using this token as your password should allow you to push to your remote repository via HTTPS. Use your username as usual.

    You may also need to update the origin for your repository if it is set to HTTPS. Do this to switch to SSH:

    bash
    $ git remote -v
    +$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
    $ git remote -v
    +$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git

    Solution 2

    GitHub username & password/access token mismatched due to prior temporary Git config setup → Reset Git global username & email config or in current repository

    To set your global username/email configuration:

    1. Open the command line.
    2. Set your username: git config --global user.name "FIRST_NAME LAST_NAME"
    3. Set your email address: git config --global user.email "MY_NAME@example.com"

    To set repository-specific username/email configuration:

    1. From the command line, change into the repository directory.
    2. Set your username: git config user.name "FIRST_NAME LAST_NAME"
    3. Set your email address: git config user.email "MY_NAME@example.com"
    4. Verify your configuration by displaying your configuration file: cat .git/config
    `,14);function u(d,h,F,m,g,A){const a=o;return e(),l("div",null,[c,t(a,{readTime:"1",words:"271"}),y])}const C=n(i,[["render",u]]);export{E as __pageData,C as default}; diff --git a/assets/getting-started.md.54a05997.lean.js b/assets/getting-started.md.975024a7.lean.js similarity index 63% rename from assets/getting-started.md.54a05997.lean.js rename to assets/getting-started.md.975024a7.lean.js index 06c09517..03ddeb51 100644 --- a/assets/getting-started.md.54a05997.lean.js +++ b/assets/getting-started.md.975024a7.lean.js @@ -1 +1 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as l,c as e,H as t,k as s,a as p,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Git push results in \\"Authentication Failed”","description":"","frontmatter":{"title":"Git push results in \\"Authentication Failed”","editLink":true,"lastUpdated":true},"headers":[],"relativePath":"getting-started.md","filePath":"getting-started.md","lastUpdated":1695377563000}'),c={name:"getting-started.md"},i=s("h1",{id:"git-push-results-in-authentication-failed",tabindex:"-1"},[p('Git push results in "Authentication Failed” '),s("a",{class:"header-anchor",href:"#git-push-results-in-authentication-failed","aria-label":'Permalink to "Git push results in "Authentication Failed”"'},"​")],-1),y=r("",14);function u(d,A,h,m,g,b){const a=o;return l(),e("div",null,[i,t(a,{readTime:"1",words:"271"}),y])}const k=n(c,[["render",u]]);export{S as __pageData,k as default}; +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as n,o as e,c as l,H as t,k as s,a as p,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const E=JSON.parse('{"title":"Git push results in \\"Authentication Failed”","description":"","frontmatter":{"title":"Git push results in \\"Authentication Failed”","editLink":true,"lastUpdated":true},"headers":[],"relativePath":"getting-started.md","filePath":"getting-started.md","lastUpdated":1699051935000}'),i={name:"getting-started.md"},c=s("h1",{id:"git-push-results-in-authentication-failed",tabindex:"-1"},[p('Git push results in "Authentication Failed” '),s("a",{class:"header-anchor",href:"#git-push-results-in-authentication-failed","aria-label":'Permalink to "Git push results in "Authentication Failed”"'},"​")],-1),y=r("",14);function u(d,h,F,m,g,A){const a=o;return e(),l("div",null,[c,t(a,{readTime:"1",words:"271"}),y])}const C=n(i,[["render",u]]);export{E as __pageData,C as default}; diff --git a/assets/index.md.bcdaa8d8.js b/assets/index.md.b89ea33b.js similarity index 96% rename from assets/index.md.bcdaa8d8.js rename to assets/index.md.b89ea33b.js index 37c46134..cbd9b7de 100644 --- a/assets/index.md.bcdaa8d8.js +++ b/assets/index.md.b89ea33b.js @@ -1 +1 @@ -import{_ as e,o as t,c as a}from"./chunks/framework.b7580407.js";const c=JSON.parse(`{"title":"Toshiki's Notebook","titleTemplate":"Eternal digital knowledge base for content creation and notes management.","description":"","frontmatter":{"layout":"home","title":"Toshiki's Notebook","titleTemplate":"Eternal digital knowledge base for content creation and notes management.","hero":{"name":"Toshiki's Notebook","text":"Research & Produce","tagline":"👨‍💻 Eternal & digital knowledge base for content creation and notes management.","image":{"src":"/logos/logo.svg","alt":"Home logo"},"actions":[{"theme":"brand","text":"👉 Start Reading","link":"/development/file-naming-convention"},{"theme":"alt","text":"🗒️ View on GitHub","link":"https://github.com/andatoshiki/toshiki-notebook"}]},"features":[{"icon":"🕒","title":"Tempus Fugit","details":"Tempus Fugit, which means \\"time flies\\" in Latin, is a phrase that highlights the fact that every person has the same 24 hours per day to learn. However, this time is never enough to learn everything. That's why recording knowledge for review is essential."},{"icon":"🫖","title":"Carpe Diem","details":"Carpe Diem, take it slow, seize the day and savor its moments. Enjoy a cup of coffee while playing blues on a 1980s-style CD player. Turn off the lights, close the curtains, and let the small lamp illuminate the space. The time is yours, relish the day, and unleash the productivity while learning."},{"icon":"💡","title":"Epiphania","details":"An epiphany, derived from the Latin word \\"epiphania,\\" is a moment of sudden and brilliant realization or insight. These moments of clarity and inspiration are precious and should be treated as such; to ensure that we don't forget these valuable ideas."}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1695377563000}`),i={name:"index.md"};function n(o,s,r,l,h,d){return t(),a("div")}const p=e(i,[["render",n]]);export{c as __pageData,p as default}; +import{_ as e,o as t,c as a}from"./chunks/framework.b7580407.js";const c=JSON.parse(`{"title":"Toshiki's Notebook","titleTemplate":"Eternal digital knowledge base for content creation and notes management.","description":"","frontmatter":{"layout":"home","title":"Toshiki's Notebook","titleTemplate":"Eternal digital knowledge base for content creation and notes management.","hero":{"name":"Toshiki's Notebook","text":"Research & Produce","tagline":"👨‍💻 Eternal & digital knowledge base for content creation and notes management.","image":{"src":"/logos/logo.svg","alt":"Home logo"},"actions":[{"theme":"brand","text":"👉 Start Reading","link":"/development/file-naming-convention"},{"theme":"alt","text":"🗒️ View on GitHub","link":"https://github.com/andatoshiki/toshiki-notebook"}]},"features":[{"icon":"🕒","title":"Tempus Fugit","details":"Tempus Fugit, which means \\"time flies\\" in Latin, is a phrase that highlights the fact that every person has the same 24 hours per day to learn. However, this time is never enough to learn everything. That's why recording knowledge for review is essential."},{"icon":"🫖","title":"Carpe Diem","details":"Carpe Diem, take it slow, seize the day and savor its moments. Enjoy a cup of coffee while playing blues on a 1980s-style CD player. Turn off the lights, close the curtains, and let the small lamp illuminate the space. The time is yours, relish the day, and unleash the productivity while learning."},{"icon":"💡","title":"Epiphania","details":"An epiphany, derived from the Latin word \\"epiphania,\\" is a moment of sudden and brilliant realization or insight. These moments of clarity and inspiration are precious and should be treated as such; to ensure that we don't forget these valuable ideas."}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1699051935000}`),i={name:"index.md"};function n(o,s,r,l,h,d){return t(),a("div")}const p=e(i,[["render",n]]);export{c as __pageData,p as default}; diff --git a/assets/index.md.bcdaa8d8.lean.js b/assets/index.md.b89ea33b.lean.js similarity index 96% rename from assets/index.md.bcdaa8d8.lean.js rename to assets/index.md.b89ea33b.lean.js index 37c46134..cbd9b7de 100644 --- a/assets/index.md.bcdaa8d8.lean.js +++ b/assets/index.md.b89ea33b.lean.js @@ -1 +1 @@ -import{_ as e,o as t,c as a}from"./chunks/framework.b7580407.js";const c=JSON.parse(`{"title":"Toshiki's Notebook","titleTemplate":"Eternal digital knowledge base for content creation and notes management.","description":"","frontmatter":{"layout":"home","title":"Toshiki's Notebook","titleTemplate":"Eternal digital knowledge base for content creation and notes management.","hero":{"name":"Toshiki's Notebook","text":"Research & Produce","tagline":"👨‍💻 Eternal & digital knowledge base for content creation and notes management.","image":{"src":"/logos/logo.svg","alt":"Home logo"},"actions":[{"theme":"brand","text":"👉 Start Reading","link":"/development/file-naming-convention"},{"theme":"alt","text":"🗒️ View on GitHub","link":"https://github.com/andatoshiki/toshiki-notebook"}]},"features":[{"icon":"🕒","title":"Tempus Fugit","details":"Tempus Fugit, which means \\"time flies\\" in Latin, is a phrase that highlights the fact that every person has the same 24 hours per day to learn. However, this time is never enough to learn everything. That's why recording knowledge for review is essential."},{"icon":"🫖","title":"Carpe Diem","details":"Carpe Diem, take it slow, seize the day and savor its moments. Enjoy a cup of coffee while playing blues on a 1980s-style CD player. Turn off the lights, close the curtains, and let the small lamp illuminate the space. The time is yours, relish the day, and unleash the productivity while learning."},{"icon":"💡","title":"Epiphania","details":"An epiphany, derived from the Latin word \\"epiphania,\\" is a moment of sudden and brilliant realization or insight. These moments of clarity and inspiration are precious and should be treated as such; to ensure that we don't forget these valuable ideas."}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1695377563000}`),i={name:"index.md"};function n(o,s,r,l,h,d){return t(),a("div")}const p=e(i,[["render",n]]);export{c as __pageData,p as default}; +import{_ as e,o as t,c as a}from"./chunks/framework.b7580407.js";const c=JSON.parse(`{"title":"Toshiki's Notebook","titleTemplate":"Eternal digital knowledge base for content creation and notes management.","description":"","frontmatter":{"layout":"home","title":"Toshiki's Notebook","titleTemplate":"Eternal digital knowledge base for content creation and notes management.","hero":{"name":"Toshiki's Notebook","text":"Research & Produce","tagline":"👨‍💻 Eternal & digital knowledge base for content creation and notes management.","image":{"src":"/logos/logo.svg","alt":"Home logo"},"actions":[{"theme":"brand","text":"👉 Start Reading","link":"/development/file-naming-convention"},{"theme":"alt","text":"🗒️ View on GitHub","link":"https://github.com/andatoshiki/toshiki-notebook"}]},"features":[{"icon":"🕒","title":"Tempus Fugit","details":"Tempus Fugit, which means \\"time flies\\" in Latin, is a phrase that highlights the fact that every person has the same 24 hours per day to learn. However, this time is never enough to learn everything. That's why recording knowledge for review is essential."},{"icon":"🫖","title":"Carpe Diem","details":"Carpe Diem, take it slow, seize the day and savor its moments. Enjoy a cup of coffee while playing blues on a 1980s-style CD player. Turn off the lights, close the curtains, and let the small lamp illuminate the space. The time is yours, relish the day, and unleash the productivity while learning."},{"icon":"💡","title":"Epiphania","details":"An epiphany, derived from the Latin word \\"epiphania,\\" is a moment of sudden and brilliant realization or insight. These moments of clarity and inspiration are precious and should be treated as such; to ensure that we don't forget these valuable ideas."}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1699051935000}`),i={name:"index.md"};function n(o,s,r,l,h,d){return t(),a("div")}const p=e(i,[["render",n]]);export{c as __pageData,p as default}; diff --git a/assets/javascript_notes_1_1-1.md.442433d3.js b/assets/javascript_notes_1_1-1.md.442433d3.js new file mode 100644 index 00000000..820617ad --- /dev/null +++ b/assets/javascript_notes_1_1-1.md.442433d3.js @@ -0,0 +1,7 @@ +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as t,k as s,a as e,Q as a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const M=JSON.parse('{"title":"1-1: Values","description":"Chapter 1-1 notes on values","frontmatter":{"title":"1-1: Values","description":"Chapter 1-1 notes on values"},"headers":[],"relativePath":"javascript/notes/1/1-1.md","filePath":"javascript/notes/1/1-1.md","lastUpdated":1699051935000}'),d={name:"javascript/notes/1/1-1.md"},u=s("h1",{id:"_1-1-values",tabindex:"-1"},[e("1-1: Values "),s("a",{class:"header-anchor",href:"#_1-1-values","aria-label":'Permalink to "1-1: Values"'},"​")],-1),h={id:"_1-1-1-numbers",tabindex:"-1"},m=s("a",{class:"header-anchor",href:"#_1-1-1-numbers","aria-label":'Permalink to "1-1-1: Numbers "'},"​",-1),g=a(`

    Values of the number type are numeric values, normally written as follows,

    js
    144
    144
    • Put this into a program, it will cause the number 144 to come into existence inside the computer, with the following bash script, 144 might looks like this in bits,

      js
      0100000001100010000000000000000000000000000000000000000000000000
      0100000001100010000000000000000000000000000000000000000000000000
    • With the following bash script, 144 will be converted into binary values in integer form,

      sh
      ip1=144 # defines a variable named ip1, with the value of 10
      +echo "obase=2;$ip1" | bc # convert the value to binary via bc
      ip1=144 # defines a variable named ip1, with the value of 10
      +echo "obase=2;$ip1" | bc # convert the value to binary via bc
      • The variable ip1 is assigned the value 144.
      • The echo command prints out the string "obase=2;144", where "obase=2;" is an argument for bc that tells it to output the result in base 2 (binary), and "10" is the decimal number we want to convert.
      • The output of the echo command is piped (using the | character) to bc, which takes the input "obase=2;144" and interprets it as a command to convert the number 10 to binary.
      • Finally, the binary equivalent of 144, which is "10010000", is printed to the terminal.

    TIP

    But the standard describes JavaScript numbers as 64-bit floating-point values, which indicates fractions and exponents are available.

    `,4),b=s("p",null,[e("Not all whole numbers "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"19")])]),s("annotation",{encoding:"application/x-tex"},"10^{19}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"19")])])])])])])])])])])]),e(" fit in a JavaScript number. There are also negative numbers, so one of the bits has to be used to store the sign of the number.")],-1),y=s("ul",null,[s("li",null,"11 bits are used to store the position of the decimal dot within the number."),s("li",null,[e("52 bits, any whole number less than "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"52")])]),s("annotation",{encoding:"application/x-tex"},"2^{52}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"52")])])])])])])])])])])]),e(", which is more than "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"15")])]),s("annotation",{encoding:"application/x-tex"},"10^{15}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"15")])])])])])])])])])])]),e(" will safely fit in a JavaScript number, numbers we are using stay well below that.")])],-1),v=a('

    Fractional numbers are written by using a dot,

    js
    9.81
    9.81

    For extreme huge or tiny numbers, we can also use "scientific" notion by adding an e, followed by the exponent of the number,

    js
    2.998e8
    2.998e8
    ',4),w=s("p",null,[e("This indicates "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2.998"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"8")]),s("mo",null,"="),s("mn",null,"29980000")]),s("annotation",{encoding:"application/x-tex"},"2.998 \\times 10^8 = 29980000")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"2.998"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"8")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"29980000")])])]),e(".")],-1),k=s("p",null,[e("Calculations with whole numbers (referred as "),s("em",null,"integers"),e(") that fits into 52 bits are guaranteed to be always precise, but calculation with fraction numbers are generally not.")],-1),C=s("ul",null,[s("li",null,[e("Such as "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),e(" cannot be precisely expressed by a finite amount of decimal digits, "),s("strong",null,"thus many numbers lose some precision when only 64 bits are available to store them.")])],-1),f=s("details",{class:"details custom-block"},[s("summary",null,"1-1-1: Numbers review"),s("ul",null,[s("li",null,[e("64 bits: A 64-bit number is a binary sequence of 64 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"64")])]),s("annotation",{encoding:"application/x-tex"},"2^{64}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"64")])])])])])])])])])])]),e(" (18,446,744,073,709,551,616) different values. This is commonly used for representing memory addresses and integers with large values in computer systems.")]),s("li",null,[e("11 bits: An 11-bit number is a binary sequence of 11 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"11")])]),s("annotation",{encoding:"application/x-tex"},"2^{11}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"11")])])])])])])])])])])]),e(" (2,048) different values. This is often used in computer systems for encoding small integers, such as color values in images.")]),s("li",null,[e("52 bits: A 52-bit number is a binary sequence of 52 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"52")])]),s("annotation",{encoding:"application/x-tex"},"2^{52}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"52")])])])])])])])])])])]),e(" (4,503,599,627,370,496) different values. This is often used for representing the significand or mantissa portion of a floating-point number in computer systems.")])])],-1),F=a(`

    1-1-2: Arithmetic

    The main thing to do with numbers is arithmetic. Arithmetic operations such as addition or multiplication take two number values and produce a new number from them, the following is an example of calculation in JavaScript.

    js
    100 + 4 * 11
    100 + 4 * 11
    • The + and * symbols are called operators.

      • + apparently stands for addition while * stands for multiplication.
    • This expression indicates the multiplication takes place first then the adding of 100 comes next as a regard to PEMDAS rules (Order of Operations).

    But we can still overwrite the steps of operation using a parenthesis around the addition,

    js
    ;(100 + 4) * 11
    ;(100 + 4) * 11

    For subtraction, there is the - operator, and division can be done with /. When operators appear together without parentheses, they are applied is determined by the precedence of the operators.

    • When multiple operators with the same precedence appear next to each other (as 1-2+1), they are applied left to right (refers to PEMDAS).
    • Precedence: Priorities.

    WARNING

    When is doubt, don't care about precedence, just add parentheses for order of operation.

    There is one more arithmetic operator, which is the % percent sign used to represent the modulo operation. The term "X modulo Y" is defined as the remainder of dividing X by Y.

    • For example, 314 % 100 is 14, 10 % 3 is 1, and 144 % 12 is 0 because there are no remainders.
    • Modulo's precedence is the same as that of multiplication and division.
    1-2: Arithmetic review
    • All of the operators in JavaScript follows precedence rules, or referred as PEMDAS in conventional math.
      • + and - has the same lowest precedence.
      • * , / and % has the same medium precedence.
      • () has the highest precedence, followed on with brackets.
    • The symbol % refers to "modulo", in mathematical reading, we say "X modulo Y" is the remainder of X over Y.

    1-1-3: Strings

    The next data type is the string. Its use is not as evident from its name as with numbers, it also fulfills a very basic role.

    • Strings are used to represent text.
    • Strings are usually written by enclosing the contents with quotes.
    js
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
    +'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
    +'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'

    TIP

    Both single and double quotes can be used to mark strings

    • As long as the quotes at the start and the end of the string match.

    Almost anything can be put between quotes, and JavaScript will make a string value out of it. But the followings are tricky to be put between quotes.

    • Newlines: The things we get when we press enter on keyboard. We uses \\n to represent.
    • New tab: Similarly like newlines, \\t indicates a new tab being indented.

    Take the following string as an example,

    js
    'Lorem ipsum dolor sit amet,\\n consectetur adipiscing elit.'
    'Lorem ipsum dolor sit amet,\\n consectetur adipiscing elit.'

    The following will be the rendered output,

    js
    Lorem ipsum dolor sit amet,
    +consectetur adipiscing elit.
    Lorem ipsum dolor sit amet,
    +consectetur adipiscing elit.

    WARNING

    But the situations where we want a backslash in a string to just be a backslash instead of a special code. By using \\\\ would render the "just slash" to \\ on output, instead of a special character, as follows,

    js
    "A newline character is written like \\"\\\\n\\"."
    "A newline character is written like \\"\\\\n\\"."

    Strings cannot be divided, multiplied, or subtracted, unlike integers. But the + operator can be used on the. It concatenates (glues) the two strings together, the following example will produce the string "concatenate".

    js
    'con' + 'cat' + 'e' + 'nate'
    'con' + 'cat' + 'e' + 'nate'
    1-1-3: Strings review
    • Nearly everything could be put into strings in JavaScript
    • String could be wrapped with "" double quotation marks or '' single quotation marks.
    • There is a tricky situation in JavaScript's string, where \\ backslash followed with a character are being introduced specially by the interpreter, such as \\n referred as newline, \\t referred as new tab.
      • \\\\ double backslash will be rendered as a single \\.
      • \\& symbols followed after slash will not contain its original function such as connecting, but will be rendered as & on output.

    1-1-3-FR: Further Reading

    From the example given in the prior section with a lot of backslashes, it might be hard to understand the concept on at what time the slash will be rendered and when it will be considered as a special character starter.

    The example is given as,

    js
    "A newline character is written like \\"\\\\n\\"."
    "A newline character is written like \\"\\\\n\\"."

    The rendered output will be on print,

    js
    A newline character is written like "\\n".
    A newline character is written like "\\n".

    the backslash character (\\) is used as an escape character to indicate that the following character(s) should be treated specially. In this case, the "\\n" sequence is an escape sequence that represents a newline character. The backslash before the n character tells the JavaScript interpreter that it should treat the n as a special character and not just as the letter "n".

    However, if we want to include an actual backslash character (\\), we will have to escape it by using to two backslashes \\\\, or else with one single slash the JavaScript interpreter will still determines it as an special operator, Thus \\\\ will print \\ on output.

    • But what about the quotation marks used within the quotation marks that wraps the string? Wouldn't JavaScript interpreter throw error?

      • In the given JavaScript string, the inner set of double quotation marks ("\\\\n") is escaped using a backslash (\\) character. This tells the JavaScript interpreter to treat the inner double quotation marks as a regular character instead of a string delimiter.

        So when the string is rendered on output, the backslash character will be removed and the inner set of quotation marks will be displayed as a regular character. The rendered string will look like this,

        js
        '\\n'
        '\\n'

        The outer set of double quotation marks in the original string delimit the entire string and will be displayed as regular quotation marks.

    Source: ChatGPT CA (Code Analysis)

    `,37);function A(_,q,x,D,B,T){const n=o,l=p("Badge");return r(),c("div",null,[u,t(n,{readTime:"9",words:"1.5k"}),s("h2",h,[e("1-1-1: Numbers "),t(l,{type:"danger",text:"must know"}),e(),m]),g,b,y,v,w,k,C,f,F])}const P=i(d,[["render",A]]);export{M as __pageData,P as default}; diff --git a/assets/javascript_notes_1_1-1.md.444635ea.lean.js b/assets/javascript_notes_1_1-1.md.442433d3.lean.js similarity index 91% rename from assets/javascript_notes_1_1-1.md.444635ea.lean.js rename to assets/javascript_notes_1_1-1.md.442433d3.lean.js index 1c0f8c3e..c57884a0 100644 --- a/assets/javascript_notes_1_1-1.md.444635ea.lean.js +++ b/assets/javascript_notes_1_1-1.md.442433d3.lean.js @@ -1 +1 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as n,k as s,a as e,Q as a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"1-1: Values","description":"Chapter 1-1 notes on values","frontmatter":{"title":"1-1: Values","description":"Chapter 1-1 notes on values"},"headers":[],"relativePath":"javascript/notes/1/1-1.md","filePath":"javascript/notes/1/1-1.md","lastUpdated":1695377563000}'),d={name:"javascript/notes/1/1-1.md"},u=s("h1",{id:"_1-1-values",tabindex:"-1"},[e("1-1: Values "),s("a",{class:"header-anchor",href:"#_1-1-values","aria-label":'Permalink to "1-1: Values"'},"​")],-1),h={id:"_1-1-1-numbers",tabindex:"-1"},m=s("a",{class:"header-anchor",href:"#_1-1-1-numbers","aria-label":'Permalink to "1-1-1: Numbers "'},"​",-1),y=a("",4),g=s("p",null,[e("Not all whole numbers "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"19")])]),s("annotation",{encoding:"application/x-tex"},"10^{19}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"19")])])])])])])])])])])]),e(" fit in a JavaScript number. There are also negative numbers, so one of the bits has to be used to store the sign of the number.")],-1),b=s("ul",null,[s("li",null,"11 bits are used to store the position of the decimal dot within the number."),s("li",null,[e("52 bits, any whole number less than "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"52")])]),s("annotation",{encoding:"application/x-tex"},"2^{52}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"52")])])])])])])])])])])]),e(", which is more than "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"15")])]),s("annotation",{encoding:"application/x-tex"},"10^{15}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"15")])])])])])])])])])])]),e(" will safely fit in a JavaScript number, numbers we are using stay well below that.")])],-1),v=a("",4),w=s("p",null,[e("This indicates "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2.998"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"8")]),s("mo",null,"="),s("mn",null,"29980000")]),s("annotation",{encoding:"application/x-tex"},"2.998 \\times 10^8 = 29980000")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"2.998"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"8")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"29980000")])])]),e(".")],-1),k=s("p",null,[e("Calculations with whole numbers (referred as "),s("em",null,"integers"),e(") that fits into 52 bits are guaranteed to be always precise, but calculation with fraction numbers are generally not.")],-1),f=s("ul",null,[s("li",null,[e("Such as "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),e(" cannot be precisely expressed by a finite amount of decimal digits, "),s("strong",null,"thus many numbers lose some precision when only 64 bits are available to store them.")])],-1),A=s("details",{class:"details custom-block"},[s("summary",null,"1-1-1: Numbers review"),s("ul",null,[s("li",null,[e("64 bits: A 64-bit number is a binary sequence of 64 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"64")])]),s("annotation",{encoding:"application/x-tex"},"2^{64}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"64")])])])])])])])])])])]),e(" (18,446,744,073,709,551,616) different values. This is commonly used for representing memory addresses and integers with large values in computer systems.")]),s("li",null,[e("11 bits: An 11-bit number is a binary sequence of 11 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"11")])]),s("annotation",{encoding:"application/x-tex"},"2^{11}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"11")])])])])])])])])])])]),e(" (2,048) different values. This is often used in computer systems for encoding small integers, such as color values in images.")]),s("li",null,[e("52 bits: A 52-bit number is a binary sequence of 52 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"52")])]),s("annotation",{encoding:"application/x-tex"},"2^{52}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"52")])])])])])])])])])])]),e(" (4,503,599,627,370,496) different values. This is often used for representing the significand or mantissa portion of a floating-point number in computer systems.")])])],-1),B=a("",37);function _(q,x,D,C,z,T){const t=o,l=p("Badge");return r(),c("div",null,[u,n(t,{readTime:"9",words:"1.5k"}),s("h2",h,[e("1-1-1: Numbers "),n(l,{type:"danger",text:"must know"}),e(),m]),y,g,b,v,w,k,f,A,B])}const N=i(d,[["render",_]]);export{P as __pageData,N as default}; +import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as t,k as s,a as e,Q as a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const M=JSON.parse('{"title":"1-1: Values","description":"Chapter 1-1 notes on values","frontmatter":{"title":"1-1: Values","description":"Chapter 1-1 notes on values"},"headers":[],"relativePath":"javascript/notes/1/1-1.md","filePath":"javascript/notes/1/1-1.md","lastUpdated":1699051935000}'),d={name:"javascript/notes/1/1-1.md"},u=s("h1",{id:"_1-1-values",tabindex:"-1"},[e("1-1: Values "),s("a",{class:"header-anchor",href:"#_1-1-values","aria-label":'Permalink to "1-1: Values"'},"​")],-1),h={id:"_1-1-1-numbers",tabindex:"-1"},m=s("a",{class:"header-anchor",href:"#_1-1-1-numbers","aria-label":'Permalink to "1-1-1: Numbers "'},"​",-1),g=a("",4),b=s("p",null,[e("Not all whole numbers "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"19")])]),s("annotation",{encoding:"application/x-tex"},"10^{19}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"19")])])])])])])])])])])]),e(" fit in a JavaScript number. There are also negative numbers, so one of the bits has to be used to store the sign of the number.")],-1),y=s("ul",null,[s("li",null,"11 bits are used to store the position of the decimal dot within the number."),s("li",null,[e("52 bits, any whole number less than "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"52")])]),s("annotation",{encoding:"application/x-tex"},"2^{52}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"52")])])])])])])])])])])]),e(", which is more than "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"15")])]),s("annotation",{encoding:"application/x-tex"},"10^{15}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"15")])])])])])])])])])])]),e(" will safely fit in a JavaScript number, numbers we are using stay well below that.")])],-1),v=a("",4),w=s("p",null,[e("This indicates "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2.998"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"8")]),s("mo",null,"="),s("mn",null,"29980000")]),s("annotation",{encoding:"application/x-tex"},"2.998 \\times 10^8 = 29980000")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"2.998"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"8")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"29980000")])])]),e(".")],-1),k=s("p",null,[e("Calculations with whole numbers (referred as "),s("em",null,"integers"),e(") that fits into 52 bits are guaranteed to be always precise, but calculation with fraction numbers are generally not.")],-1),C=s("ul",null,[s("li",null,[e("Such as "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),e(" cannot be precisely expressed by a finite amount of decimal digits, "),s("strong",null,"thus many numbers lose some precision when only 64 bits are available to store them.")])],-1),f=s("details",{class:"details custom-block"},[s("summary",null,"1-1-1: Numbers review"),s("ul",null,[s("li",null,[e("64 bits: A 64-bit number is a binary sequence of 64 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"64")])]),s("annotation",{encoding:"application/x-tex"},"2^{64}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"64")])])])])])])])])])])]),e(" (18,446,744,073,709,551,616) different values. This is commonly used for representing memory addresses and integers with large values in computer systems.")]),s("li",null,[e("11 bits: An 11-bit number is a binary sequence of 11 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"11")])]),s("annotation",{encoding:"application/x-tex"},"2^{11}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"11")])])])])])])])])])])]),e(" (2,048) different values. This is often used in computer systems for encoding small integers, such as color values in images.")]),s("li",null,[e("52 bits: A 52-bit number is a binary sequence of 52 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"52")])]),s("annotation",{encoding:"application/x-tex"},"2^{52}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"52")])])])])])])])])])])]),e(" (4,503,599,627,370,496) different values. This is often used for representing the significand or mantissa portion of a floating-point number in computer systems.")])])],-1),F=a("",37);function A(_,q,x,D,B,T){const n=o,l=p("Badge");return r(),c("div",null,[u,t(n,{readTime:"9",words:"1.5k"}),s("h2",h,[e("1-1-1: Numbers "),t(l,{type:"danger",text:"must know"}),e(),m]),g,b,y,v,w,k,C,f,F])}const P=i(d,[["render",A]]);export{M as __pageData,P as default}; diff --git a/assets/javascript_notes_1_1-1.md.444635ea.js b/assets/javascript_notes_1_1-1.md.444635ea.js deleted file mode 100644 index b82c6b7d..00000000 --- a/assets/javascript_notes_1_1-1.md.444635ea.js +++ /dev/null @@ -1,7 +0,0 @@ -import{_ as o}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,C as p,o as r,c,H as n,k as s,a as e,Q as a}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const P=JSON.parse('{"title":"1-1: Values","description":"Chapter 1-1 notes on values","frontmatter":{"title":"1-1: Values","description":"Chapter 1-1 notes on values"},"headers":[],"relativePath":"javascript/notes/1/1-1.md","filePath":"javascript/notes/1/1-1.md","lastUpdated":1695377563000}'),d={name:"javascript/notes/1/1-1.md"},u=s("h1",{id:"_1-1-values",tabindex:"-1"},[e("1-1: Values "),s("a",{class:"header-anchor",href:"#_1-1-values","aria-label":'Permalink to "1-1: Values"'},"​")],-1),h={id:"_1-1-1-numbers",tabindex:"-1"},m=s("a",{class:"header-anchor",href:"#_1-1-1-numbers","aria-label":'Permalink to "1-1-1: Numbers "'},"​",-1),y=a(`

    Values of the number type are numeric values, normally written as follows,

    js
    144
    144
    • Put this into a program, it will cause the number 144 to come into existence inside the computer, with the following bash script, 144 might looks like this in bits,

      js
      0100000001100010000000000000000000000000000000000000000000000000
      0100000001100010000000000000000000000000000000000000000000000000
    • With the following bash script, 144 will be converted into binary values in integer form,

      sh
      ip1=144 # defines a variable named ip1, with the value of 10
      -echo "obase=2;$ip1" | bc # convert the value to binary via bc
      ip1=144 # defines a variable named ip1, with the value of 10
      -echo "obase=2;$ip1" | bc # convert the value to binary via bc
      • The variable ip1 is assigned the value 144.
      • The echo command prints out the string "obase=2;144", where "obase=2;" is an argument for bc that tells it to output the result in base 2 (binary), and "10" is the decimal number we want to convert.
      • The output of the echo command is piped (using the | character) to bc, which takes the input "obase=2;144" and interprets it as a command to convert the number 10 to binary.
      • Finally, the binary equivalent of 144, which is "10010000", is printed to the terminal.

    TIP

    But the standard describes JavaScript numbers as 64-bit floating-point values, which indicates fractions and exponents are available.

    `,4),g=s("p",null,[e("Not all whole numbers "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"19")])]),s("annotation",{encoding:"application/x-tex"},"10^{19}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"19")])])])])])])])])])])]),e(" fit in a JavaScript number. There are also negative numbers, so one of the bits has to be used to store the sign of the number.")],-1),b=s("ul",null,[s("li",null,"11 bits are used to store the position of the decimal dot within the number."),s("li",null,[e("52 bits, any whole number less than "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"52")])]),s("annotation",{encoding:"application/x-tex"},"2^{52}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"52")])])])])])])])])])])]),e(", which is more than "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"15")])]),s("annotation",{encoding:"application/x-tex"},"10^{15}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"15")])])])])])])])])])])]),e(" will safely fit in a JavaScript number, numbers we are using stay well below that.")])],-1),v=a('

    Fractional numbers are written by using a dot,

    js
    9.81
    9.81

    For extreme huge or tiny numbers, we can also use "scientific" notion by adding an e, followed by the exponent of the number,

    js
    2.998e8
    2.998e8
    ',4),w=s("p",null,[e("This indicates "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"2.998"),s("mo",null,"×"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"8")]),s("mo",null,"="),s("mn",null,"29980000")]),s("annotation",{encoding:"application/x-tex"},"2.998 \\times 10^8 = 29980000")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"2.998"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"8")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"29980000")])])]),e(".")],-1),k=s("p",null,[e("Calculations with whole numbers (referred as "),s("em",null,"integers"),e(") that fits into 52 bits are guaranteed to be always precise, but calculation with fraction numbers are generally not.")],-1),f=s("ul",null,[s("li",null,[e("Such as "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"π")]),s("annotation",{encoding:"application/x-tex"},"\\pi")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"π")])])]),e(" cannot be precisely expressed by a finite amount of decimal digits, "),s("strong",null,"thus many numbers lose some precision when only 64 bits are available to store them.")])],-1),A=s("details",{class:"details custom-block"},[s("summary",null,"1-1-1: Numbers review"),s("ul",null,[s("li",null,[e("64 bits: A 64-bit number is a binary sequence of 64 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"64")])]),s("annotation",{encoding:"application/x-tex"},"2^{64}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"64")])])])])])])])])])])]),e(" (18,446,744,073,709,551,616) different values. This is commonly used for representing memory addresses and integers with large values in computer systems.")]),s("li",null,[e("11 bits: An 11-bit number is a binary sequence of 11 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"11")])]),s("annotation",{encoding:"application/x-tex"},"2^{11}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"11")])])])])])])])])])])]),e(" (2,048) different values. This is often used in computer systems for encoding small integers, such as color values in images.")]),s("li",null,[e("52 bits: A 52-bit number is a binary sequence of 52 bits, which can represent "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mn",null,"2"),s("mn",null,"52")])]),s("annotation",{encoding:"application/x-tex"},"2^{52}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"52")])])])])])])])])])])]),e(" (4,503,599,627,370,496) different values. This is often used for representing the significand or mantissa portion of a floating-point number in computer systems.")])])],-1),B=a(`

    1-1-2: Arithmetic

    The main thing to do with numbers is arithmetic. Arithmetic operations such as addition or multiplication take two number values and produce a new number from them, the following is an example of calculation in JavaScript.

    js
    100 + 4 * 11
    100 + 4 * 11
    • The + and * symbols are called operators.

      • + apparently stands for addition while * stands for multiplication.
    • This expression indicates the multiplication takes place first then the adding of 100 comes next as a regard to PEMDAS rules (Order of Operations).

    But we can still overwrite the steps of operation using a parenthesis around the addition,

    js
    ;(100 + 4) * 11
    ;(100 + 4) * 11

    For subtraction, there is the - operator, and division can be done with /. When operators appear together without parentheses, they are applied is determined by the precedence of the operators.

    • When multiple operators with the same precedence appear next to each other (as 1-2+1), they are applied left to right (refers to PEMDAS).
    • Precedence: Priorities.

    WARNING

    When is doubt, don't care about precedence, just add parentheses for order of operation.

    There is one more arithmetic operator, which is the % percent sign used to represent the modulo operation. The term "X modulo Y" is defined as the remainder of dividing X by Y.

    • For example, 314 % 100 is 14, 10 % 3 is 1, and 144 % 12 is 0 because there are no remainders.
    • Modulo's precedence is the same as that of multiplication and division.
    1-2: Arithmetic review
    • All of the operators in JavaScript follows precedence rules, or referred as PEMDAS in conventional math.
      • + and - has the same lowest precedence.
      • * , / and % has the same medium precedence.
      • () has the highest precedence, followed on with brackets.
    • The symbol % refers to "modulo", in mathematical reading, we say "X modulo Y" is the remainder of X over Y.

    1-1-3: Strings

    The next data type is the string. Its use is not as evident from its name as with numbers, it also fulfills a very basic role.

    • Strings are used to represent text.
    • Strings are usually written by enclosing the contents with quotes.
    js
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
    -'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
    -'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'

    TIP

    Both single and double quotes can be used to mark strings

    • As long as the quotes at the start and the end of the string match.

    Almost anything can be put between quotes, and JavaScript will make a string value out of it. But the followings are tricky to be put between quotes.

    • Newlines: The things we get when we press enter on keyboard. We uses \\n to represent.
    • New tab: Similarly like newlines, \\t indicates a new tab being indented.

    Take the following string as an example,

    js
    'Lorem ipsum dolor sit amet,\\n consectetur adipiscing elit.'
    'Lorem ipsum dolor sit amet,\\n consectetur adipiscing elit.'

    The following will be the rendered output,

    js
    Lorem ipsum dolor sit amet,
    -consectetur adipiscing elit.
    Lorem ipsum dolor sit amet,
    -consectetur adipiscing elit.

    WARNING

    But the situations where we want a backslash in a string to just be a backslash instead of a special code. By using \\\\ would render the "just slash" to \\ on output, instead of a special character, as follows,

    js
    "A newline character is written like \\"\\\\n\\"."
    "A newline character is written like \\"\\\\n\\"."

    Strings cannot be divided, multiplied, or subtracted, unlike integers. But the + operator can be used on the. It concatenates (glues) the two strings together, the following example will produce the string "concatenate".

    js
    'con' + 'cat' + 'e' + 'nate'
    'con' + 'cat' + 'e' + 'nate'
    1-1-3: Strings review
    • Nearly everything could be put into strings in JavaScript
    • String could be wrapped with "" double quotation marks or '' single quotation marks.
    • There is a tricky situation in JavaScript's string, where \\ backslash followed with a character are being introduced specially by the interpreter, such as \\n referred as newline, \\t referred as new tab.
      • \\\\ double backslash will be rendered as a single \\.
      • \\& symbols followed after slash will not contain its original function such as connecting, but will be rendered as & on output.

    1-1-3-FR: Further Reading

    From the example given in the prior section with a lot of backslashes, it might be hard to understand the concept on at what time the slash will be rendered and when it will be considered as a special character starter.

    The example is given as,

    js
    "A newline character is written like \\"\\\\n\\"."
    "A newline character is written like \\"\\\\n\\"."

    The rendered output will be on print,

    js
    A newline character is written like "\\n".
    A newline character is written like "\\n".

    the backslash character (\\) is used as an escape character to indicate that the following character(s) should be treated specially. In this case, the "\\n" sequence is an escape sequence that represents a newline character. The backslash before the n character tells the JavaScript interpreter that it should treat the n as a special character and not just as the letter "n".

    However, if we want to include an actual backslash character (\\), we will have to escape it by using to two backslashes \\\\, or else with one single slash the JavaScript interpreter will still determines it as an special operator, Thus \\\\ will print \\ on output.

    • But what about the quotation marks used within the quotation marks that wraps the string? Wouldn't JavaScript interpreter throw error?

      • In the given JavaScript string, the inner set of double quotation marks ("\\\\n") is escaped using a backslash (\\) character. This tells the JavaScript interpreter to treat the inner double quotation marks as a regular character instead of a string delimiter.

        So when the string is rendered on output, the backslash character will be removed and the inner set of quotation marks will be displayed as a regular character. The rendered string will look like this,

        js
        '\\n'
        '\\n'

        The outer set of double quotation marks in the original string delimit the entire string and will be displayed as regular quotation marks.

    Source: ChatGPT CA (Code Analysis)

    `,37);function _(q,x,D,C,z,T){const t=o,l=p("Badge");return r(),c("div",null,[u,n(t,{readTime:"9",words:"1.5k"}),s("h2",h,[e("1-1-1: Numbers "),n(l,{type:"danger",text:"must know"}),e(),m]),y,g,b,v,w,k,f,A,B])}const N=i(d,[["render",_]]);export{P as __pageData,N as default}; diff --git a/assets/javascript_notes_1_1-2.md.cddd09d6.js b/assets/javascript_notes_1_1-2.md.cf1c6a03.js similarity index 84% rename from assets/javascript_notes_1_1-2.md.cddd09d6.js rename to assets/javascript_notes_1_1-2.md.cf1c6a03.js index 91d328ff..f8979cce 100644 --- a/assets/javascript_notes_1_1-2.md.cddd09d6.js +++ b/assets/javascript_notes_1_1-2.md.cf1c6a03.js @@ -1 +1 @@ -import{_ as t,o as e,c as a}from"./chunks/framework.b7580407.js";const l=JSON.parse('{"title":"1-2","description":"","frontmatter":{"title":"1-2"},"headers":[],"relativePath":"javascript/notes/1/1-2.md","filePath":"javascript/notes/1/1-2.md","lastUpdated":1695377563000}'),s={name:"javascript/notes/1/1-2.md"};function r(o,c,n,p,i,d){return e(),a("div")}const m=t(s,[["render",r]]);export{l as __pageData,m as default}; +import{_ as t,o as e,c as a}from"./chunks/framework.b7580407.js";const l=JSON.parse('{"title":"1-2","description":"","frontmatter":{"title":"1-2"},"headers":[],"relativePath":"javascript/notes/1/1-2.md","filePath":"javascript/notes/1/1-2.md","lastUpdated":1699051935000}'),s={name:"javascript/notes/1/1-2.md"};function r(o,c,n,p,i,d){return e(),a("div")}const m=t(s,[["render",r]]);export{l as __pageData,m as default}; diff --git a/assets/javascript_notes_1_1-2.md.cddd09d6.lean.js b/assets/javascript_notes_1_1-2.md.cf1c6a03.lean.js similarity index 84% rename from assets/javascript_notes_1_1-2.md.cddd09d6.lean.js rename to assets/javascript_notes_1_1-2.md.cf1c6a03.lean.js index 91d328ff..f8979cce 100644 --- a/assets/javascript_notes_1_1-2.md.cddd09d6.lean.js +++ b/assets/javascript_notes_1_1-2.md.cf1c6a03.lean.js @@ -1 +1 @@ -import{_ as t,o as e,c as a}from"./chunks/framework.b7580407.js";const l=JSON.parse('{"title":"1-2","description":"","frontmatter":{"title":"1-2"},"headers":[],"relativePath":"javascript/notes/1/1-2.md","filePath":"javascript/notes/1/1-2.md","lastUpdated":1695377563000}'),s={name:"javascript/notes/1/1-2.md"};function r(o,c,n,p,i,d){return e(),a("div")}const m=t(s,[["render",r]]);export{l as __pageData,m as default}; +import{_ as t,o as e,c as a}from"./chunks/framework.b7580407.js";const l=JSON.parse('{"title":"1-2","description":"","frontmatter":{"title":"1-2"},"headers":[],"relativePath":"javascript/notes/1/1-2.md","filePath":"javascript/notes/1/1-2.md","lastUpdated":1699051935000}'),s={name:"javascript/notes/1/1-2.md"};function r(o,c,n,p,i,d){return e(),a("div")}const m=t(s,[["render",r]]);export{l as __pageData,m as default}; diff --git a/assets/jp_index.md.5b353799.js b/assets/jp_index.md.f593c74c.js similarity index 97% rename from assets/jp_index.md.5b353799.js rename to assets/jp_index.md.f593c74c.js index ab7faeb3..0b92153d 100644 --- a/assets/jp_index.md.5b353799.js +++ b/assets/jp_index.md.f593c74c.js @@ -1 +1 @@ -import{_ as e,o as t,c as i}from"./chunks/framework.b7580407.js";const c=JSON.parse('{"title":"俊樹のノート","titleTemplate":"コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","description":"","frontmatter":{"layout":"home","title":"俊樹のノート","titleTemplate":"コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","hero":{"name":"俊樹のノート","text":"研究して作成","tagline":"👨‍💻 コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","image":{"src":"/logos/logo.svg","alt":"Home logo"},"actions":[{"theme":"brand","text":"👉 始め","link":"/getting-started"},{"theme":"alt","text":"🗒️ GitHub で見る","link":"https://github.com/andatoshiki/toshiki-notebook"}]},"features":[{"icon":"🕒","title":"Tempus Fugit","details":"Tempus Fugit とは、ラテン語で「時が飛ぶ」という意味のフレーズで、誰もが同じ1日24時間しかないことを強調しています. しかし、この時間だけでは全 てを学ぶには十分ではありません. だからこそ、知識を記録し復習することが重要なのです."},{"icon":"☕","title":"Carpe Diem","details":"Carpe Diem、今日を生き抜き、その瞬間を堪能しましょう。1980年代風のCDプレイヤーでブルーズを聴きながらコーヒーを飲むのも良いでしょう。ライトを消し、カーテンを閉め、小さなランプでスペースを照らしましょう。時間はあなたのものです。今日を味わい、学びながら生産性を発揮してください."},{"icon":"💡","title":"Epiphania","details":"エピファニーは、ラテン語の epiphania に由来する言葉で、突然の輝かしい気づきや洞察力を示す瞬間です. このような明晰な洞察力を持った瞬間は貴重であり、私たちがこれらの貴重なアイデアを忘れないようにするためにも大切に扱うべきです."}]},"headers":[],"relativePath":"jp/index.md","filePath":"jp/index.md","lastUpdated":1695377563000}'),a={name:"jp/index.md"};function o(n,s,l,p,d,r){return t(),i("div")}const _=e(a,[["render",o]]);export{c as __pageData,_ as default}; +import{_ as e,o as t,c as i}from"./chunks/framework.b7580407.js";const c=JSON.parse('{"title":"俊樹のノート","titleTemplate":"コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","description":"","frontmatter":{"layout":"home","title":"俊樹のノート","titleTemplate":"コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","hero":{"name":"俊樹のノート","text":"研究して作成","tagline":"👨‍💻 コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","image":{"src":"/logos/logo.svg","alt":"Home logo"},"actions":[{"theme":"brand","text":"👉 始め","link":"/getting-started"},{"theme":"alt","text":"🗒️ GitHub で見る","link":"https://github.com/andatoshiki/toshiki-notebook"}]},"features":[{"icon":"🕒","title":"Tempus Fugit","details":"Tempus Fugit とは、ラテン語で「時が飛ぶ」という意味のフレーズで、誰もが同じ1日24時間しかないことを強調しています. しかし、この時間だけでは全 てを学ぶには十分ではありません. だからこそ、知識を記録し復習することが重要なのです."},{"icon":"☕","title":"Carpe Diem","details":"Carpe Diem、今日を生き抜き、その瞬間を堪能しましょう。1980年代風のCDプレイヤーでブルーズを聴きながらコーヒーを飲むのも良いでしょう。ライトを消し、カーテンを閉め、小さなランプでスペースを照らしましょう。時間はあなたのものです。今日を味わい、学びながら生産性を発揮してください."},{"icon":"💡","title":"Epiphania","details":"エピファニーは、ラテン語の epiphania に由来する言葉で、突然の輝かしい気づきや洞察力を示す瞬間です. このような明晰な洞察力を持った瞬間は貴重であり、私たちがこれらの貴重なアイデアを忘れないようにするためにも大切に扱うべきです."}]},"headers":[],"relativePath":"jp/index.md","filePath":"jp/index.md","lastUpdated":1699051935000}'),a={name:"jp/index.md"};function o(n,s,l,p,d,r){return t(),i("div")}const _=e(a,[["render",o]]);export{c as __pageData,_ as default}; diff --git a/assets/jp_index.md.5b353799.lean.js b/assets/jp_index.md.f593c74c.lean.js similarity index 97% rename from assets/jp_index.md.5b353799.lean.js rename to assets/jp_index.md.f593c74c.lean.js index ab7faeb3..0b92153d 100644 --- a/assets/jp_index.md.5b353799.lean.js +++ b/assets/jp_index.md.f593c74c.lean.js @@ -1 +1 @@ -import{_ as e,o as t,c as i}from"./chunks/framework.b7580407.js";const c=JSON.parse('{"title":"俊樹のノート","titleTemplate":"コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","description":"","frontmatter":{"layout":"home","title":"俊樹のノート","titleTemplate":"コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","hero":{"name":"俊樹のノート","text":"研究して作成","tagline":"👨‍💻 コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","image":{"src":"/logos/logo.svg","alt":"Home logo"},"actions":[{"theme":"brand","text":"👉 始め","link":"/getting-started"},{"theme":"alt","text":"🗒️ GitHub で見る","link":"https://github.com/andatoshiki/toshiki-notebook"}]},"features":[{"icon":"🕒","title":"Tempus Fugit","details":"Tempus Fugit とは、ラテン語で「時が飛ぶ」という意味のフレーズで、誰もが同じ1日24時間しかないことを強調しています. しかし、この時間だけでは全 てを学ぶには十分ではありません. だからこそ、知識を記録し復習することが重要なのです."},{"icon":"☕","title":"Carpe Diem","details":"Carpe Diem、今日を生き抜き、その瞬間を堪能しましょう。1980年代風のCDプレイヤーでブルーズを聴きながらコーヒーを飲むのも良いでしょう。ライトを消し、カーテンを閉め、小さなランプでスペースを照らしましょう。時間はあなたのものです。今日を味わい、学びながら生産性を発揮してください."},{"icon":"💡","title":"Epiphania","details":"エピファニーは、ラテン語の epiphania に由来する言葉で、突然の輝かしい気づきや洞察力を示す瞬間です. このような明晰な洞察力を持った瞬間は貴重であり、私たちがこれらの貴重なアイデアを忘れないようにするためにも大切に扱うべきです."}]},"headers":[],"relativePath":"jp/index.md","filePath":"jp/index.md","lastUpdated":1695377563000}'),a={name:"jp/index.md"};function o(n,s,l,p,d,r){return t(),i("div")}const _=e(a,[["render",o]]);export{c as __pageData,_ as default}; +import{_ as e,o as t,c as i}from"./chunks/framework.b7580407.js";const c=JSON.parse('{"title":"俊樹のノート","titleTemplate":"コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","description":"","frontmatter":{"layout":"home","title":"俊樹のノート","titleTemplate":"コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","hero":{"name":"俊樹のノート","text":"研究して作成","tagline":"👨‍💻 コンテンツ作成やメモ管理のための永遠のデジタル知識ベース","image":{"src":"/logos/logo.svg","alt":"Home logo"},"actions":[{"theme":"brand","text":"👉 始め","link":"/getting-started"},{"theme":"alt","text":"🗒️ GitHub で見る","link":"https://github.com/andatoshiki/toshiki-notebook"}]},"features":[{"icon":"🕒","title":"Tempus Fugit","details":"Tempus Fugit とは、ラテン語で「時が飛ぶ」という意味のフレーズで、誰もが同じ1日24時間しかないことを強調しています. しかし、この時間だけでは全 てを学ぶには十分ではありません. だからこそ、知識を記録し復習することが重要なのです."},{"icon":"☕","title":"Carpe Diem","details":"Carpe Diem、今日を生き抜き、その瞬間を堪能しましょう。1980年代風のCDプレイヤーでブルーズを聴きながらコーヒーを飲むのも良いでしょう。ライトを消し、カーテンを閉め、小さなランプでスペースを照らしましょう。時間はあなたのものです。今日を味わい、学びながら生産性を発揮してください."},{"icon":"💡","title":"Epiphania","details":"エピファニーは、ラテン語の epiphania に由来する言葉で、突然の輝かしい気づきや洞察力を示す瞬間です. このような明晰な洞察力を持った瞬間は貴重であり、私たちがこれらの貴重なアイデアを忘れないようにするためにも大切に扱うべきです."}]},"headers":[],"relativePath":"jp/index.md","filePath":"jp/index.md","lastUpdated":1699051935000}'),a={name:"jp/index.md"};function o(n,s,l,p,d,r){return t(),i("div")}const _=e(a,[["render",o]]);export{c as __pageData,_ as default}; diff --git a/assets/roadmap.md.d668d571.js b/assets/roadmap.md.233c3dec.js similarity index 98% rename from assets/roadmap.md.d668d571.js rename to assets/roadmap.md.233c3dec.js index aae88c30..de751bda 100644 --- a/assets/roadmap.md.d668d571.js +++ b/assets/roadmap.md.233c3dec.js @@ -1 +1 @@ -import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as a,c as l,H as c,k as t,a as o,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Theme","description":"","frontmatter":{},"headers":[],"relativePath":"roadmap.md","filePath":"roadmap.md","lastUpdated":1695377563000}'),n={name:"roadmap.md"},d=t("h1",{id:"theme",tabindex:"-1"},[o("Theme "),t("a",{class:"header-anchor",href:"#theme","aria-label":'Permalink to "Theme"'},"​")],-1),k=r('

    Homepage

    • Finish three hero action blocks with keywords and its corresponded descriptions.

    • Finish my learning platform section using SVGs of different online academies from simple icons.

      • Descriptions

      • Icon in SVG format

      • Platform name

      • Linkable SVG icon/button

        • Khan academy
        • GitHub
        • Libretext
        • OpenStax
        • BCcampus
        • Wikibooks
        • Wikipedia
        • Bookboon
        • [ ]

    Configs

    • Header configs including different properties and meta configs.
    • Complete navigation configuration.
    • Complete sidebar configs for different directories.
    • Vitepress sidebar generation plugin for huge bundled clips article directory.

    Articles

    • <head> tag documentation or guide by joshbuchea/HEAD.
    • Write index page for every directory, no Chat GPT allowed.
    • Chemistry review notes.
    • JavaScript 0-100 notes per chapter.
      • Marijn Haverbeke - Eloquent JavaScript_ A Modern Introduction to Programming (2011, No Starch Press)
    • Outliers novel clips
    • Migrate clipped articles and archives from Notion to Vitepress.
    • Fresh copy of "How To Ask Questions The Smart Way" by Eric Steven Raymond
    ',8);function h(p,m,b,u,x,f){const e=s;return a(),l("div",null,[d,c(e,{readTime:"1",words:"203"}),k])}const q=i(n,[["render",h]]);export{v as __pageData,q as default}; +import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as a,c as l,H as c,k as t,a as o,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Theme","description":"","frontmatter":{},"headers":[],"relativePath":"roadmap.md","filePath":"roadmap.md","lastUpdated":1699051935000}'),n={name:"roadmap.md"},d=t("h1",{id:"theme",tabindex:"-1"},[o("Theme "),t("a",{class:"header-anchor",href:"#theme","aria-label":'Permalink to "Theme"'},"​")],-1),k=r('

    Homepage

    • Finish three hero action blocks with keywords and its corresponded descriptions.

    • Finish my learning platform section using SVGs of different online academies from simple icons.

      • Descriptions

      • Icon in SVG format

      • Platform name

      • Linkable SVG icon/button

        • Khan academy
        • GitHub
        • Libretext
        • OpenStax
        • BCcampus
        • Wikibooks
        • Wikipedia
        • Bookboon
        • [ ]

    Configs

    • Header configs including different properties and meta configs.
    • Complete navigation configuration.
    • Complete sidebar configs for different directories.
    • Vitepress sidebar generation plugin for huge bundled clips article directory.

    Articles

    • <head> tag documentation or guide by joshbuchea/HEAD.
    • Write index page for every directory, no Chat GPT allowed.
    • Chemistry review notes.
    • JavaScript 0-100 notes per chapter.
      • Marijn Haverbeke - Eloquent JavaScript_ A Modern Introduction to Programming (2011, No Starch Press)
    • Outliers novel clips
    • Migrate clipped articles and archives from Notion to Vitepress.
    • Fresh copy of "How To Ask Questions The Smart Way" by Eric Steven Raymond
    ',8);function h(p,m,b,u,x,f){const e=s;return a(),l("div",null,[d,c(e,{readTime:"1",words:"203"}),k])}const q=i(n,[["render",h]]);export{v as __pageData,q as default}; diff --git a/assets/roadmap.md.d668d571.lean.js b/assets/roadmap.md.233c3dec.lean.js similarity index 91% rename from assets/roadmap.md.d668d571.lean.js rename to assets/roadmap.md.233c3dec.lean.js index 0aeb601c..11d59292 100644 --- a/assets/roadmap.md.d668d571.lean.js +++ b/assets/roadmap.md.233c3dec.lean.js @@ -1 +1 @@ -import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as a,c as l,H as c,k as t,a as o,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Theme","description":"","frontmatter":{},"headers":[],"relativePath":"roadmap.md","filePath":"roadmap.md","lastUpdated":1695377563000}'),n={name:"roadmap.md"},d=t("h1",{id:"theme",tabindex:"-1"},[o("Theme "),t("a",{class:"header-anchor",href:"#theme","aria-label":'Permalink to "Theme"'},"​")],-1),k=r("",8);function h(p,m,b,u,x,f){const e=s;return a(),l("div",null,[d,c(e,{readTime:"1",words:"203"}),k])}const q=i(n,[["render",h]]);export{v as __pageData,q as default}; +import{_ as s}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as i,o as a,c as l,H as c,k as t,a as o,Q as r}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Theme","description":"","frontmatter":{},"headers":[],"relativePath":"roadmap.md","filePath":"roadmap.md","lastUpdated":1699051935000}'),n={name:"roadmap.md"},d=t("h1",{id:"theme",tabindex:"-1"},[o("Theme "),t("a",{class:"header-anchor",href:"#theme","aria-label":'Permalink to "Theme"'},"​")],-1),k=r("",8);function h(p,m,b,u,x,f){const e=s;return a(),l("div",null,[d,c(e,{readTime:"1",words:"203"}),k])}const q=i(n,[["render",h]]);export{v as __pageData,q as default}; diff --git a/assets/save_reading_index.md.d900b2c8.js b/assets/save_reading_index.md.684b6d50.js similarity index 92% rename from assets/save_reading_index.md.d900b2c8.js rename to assets/save_reading_index.md.684b6d50.js index fab3fa41..77e9f1d3 100644 --- a/assets/save_reading_index.md.d900b2c8.js +++ b/assets/save_reading_index.md.684b6d50.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as s,H as r,k as e,a as d}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Welcome to Reading Notes","description":"","frontmatter":{},"headers":[],"relativePath":"save/reading/index.md","filePath":"save/reading/index.md","lastUpdated":1695377563000}'),i={name:"save/reading/index.md"},c=e("h1",{id:"welcome-to-reading-notes",tabindex:"-1"},[d("Welcome to Reading Notes "),e("a",{class:"header-anchor",href:"#welcome-to-reading-notes","aria-label":'Permalink to "Welcome to Reading Notes"'},"​")],-1);function m(l,_,p,f,g,h){const a=t;return n(),s("div",null,[c,r(a,{readTime:"1",words:"4"})])}const $=o(i,[["render",m]]);export{v as __pageData,$ as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as s,H as r,k as e,a as d}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Welcome to Reading Notes","description":"","frontmatter":{},"headers":[],"relativePath":"save/reading/index.md","filePath":"save/reading/index.md","lastUpdated":1699051935000}'),i={name:"save/reading/index.md"},c=e("h1",{id:"welcome-to-reading-notes",tabindex:"-1"},[d("Welcome to Reading Notes "),e("a",{class:"header-anchor",href:"#welcome-to-reading-notes","aria-label":'Permalink to "Welcome to Reading Notes"'},"​")],-1);function m(l,_,p,f,g,h){const a=t;return n(),s("div",null,[c,r(a,{readTime:"1",words:"4"})])}const $=o(i,[["render",m]]);export{v as __pageData,$ as default}; diff --git a/assets/save_reading_index.md.d900b2c8.lean.js b/assets/save_reading_index.md.684b6d50.lean.js similarity index 92% rename from assets/save_reading_index.md.d900b2c8.lean.js rename to assets/save_reading_index.md.684b6d50.lean.js index fab3fa41..77e9f1d3 100644 --- a/assets/save_reading_index.md.d900b2c8.lean.js +++ b/assets/save_reading_index.md.684b6d50.lean.js @@ -1 +1 @@ -import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as s,H as r,k as e,a as d}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Welcome to Reading Notes","description":"","frontmatter":{},"headers":[],"relativePath":"save/reading/index.md","filePath":"save/reading/index.md","lastUpdated":1695377563000}'),i={name:"save/reading/index.md"},c=e("h1",{id:"welcome-to-reading-notes",tabindex:"-1"},[d("Welcome to Reading Notes "),e("a",{class:"header-anchor",href:"#welcome-to-reading-notes","aria-label":'Permalink to "Welcome to Reading Notes"'},"​")],-1);function m(l,_,p,f,g,h){const a=t;return n(),s("div",null,[c,r(a,{readTime:"1",words:"4"})])}const $=o(i,[["render",m]]);export{v as __pageData,$ as default}; +import{_ as t}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as s,H as r,k as e,a as d}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const v=JSON.parse('{"title":"Welcome to Reading Notes","description":"","frontmatter":{},"headers":[],"relativePath":"save/reading/index.md","filePath":"save/reading/index.md","lastUpdated":1699051935000}'),i={name:"save/reading/index.md"},c=e("h1",{id:"welcome-to-reading-notes",tabindex:"-1"},[d("Welcome to Reading Notes "),e("a",{class:"header-anchor",href:"#welcome-to-reading-notes","aria-label":'Permalink to "Welcome to Reading Notes"'},"​")],-1);function m(l,_,p,f,g,h){const a=t;return n(),s("div",null,[c,r(a,{readTime:"1",words:"4"})])}const $=o(i,[["render",m]]);export{v as __pageData,$ as default}; diff --git a/assets/save_reading_outliers_1.md.64c11331.js b/assets/save_reading_outliers_1.md.9f6d6e06.js similarity index 99% rename from assets/save_reading_outliers_1.md.64c11331.js rename to assets/save_reading_outliers_1.md.9f6d6e06.js index 70c831eb..61868e96 100644 --- a/assets/save_reading_outliers_1.md.64c11331.js +++ b/assets/save_reading_outliers_1.md.9f6d6e06.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as s,c as r,H as n,k as e,a as i,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Introduction & Chapter 1: The Roseto Mystery","description":"Chapter 1 summary clips from Sparknotes of novel Outliers by Malcom Gladwells","frontmatter":{"author":"查尔斯","title":"Introduction & Chapter 1: The Roseto Mystery","description":"Chapter 1 summary clips from Sparknotes of novel Outliers by Malcom Gladwells"},"headers":[],"relativePath":"save/reading/outliers/1.md","filePath":"save/reading/outliers/1.md","lastUpdated":1695377563000}'),l={name:"save/reading/outliers/1.md"},d=e("h1",{id:"introduction-chapter-1-the-roseto-mystery",tabindex:"-1"},[i("Introduction & Chapter 1: The Roseto Mystery "),e("a",{class:"header-anchor",href:"#introduction-chapter-1-the-roseto-mystery","aria-label":'Permalink to "Introduction & Chapter 1: The Roseto Mystery"'},"​")],-1),c=h('

    Summary: Introduction: The Roseto Mystery

    Section 1.

    In the late 1800s, immigrants from Roseto Valfortore, Italy, came to Pennsylvania to work in the slate quarry near the town of Bangor. The settlers established a new community, named after their old one: Roseto. They built schools, a park, small shops, and more than a dozen factories. They kept to themselves and did not interact much with the predominantly German and English populations of the towns around them.

    In the 1950s, a local doctor told Stewart Wolf, a medical researcher, that hardly anyone in Roseto under age sixty-five had heart disease. Wolf was curious. He did blood draws and EKG scans, and he analyzed physicians’ records and death certificates. Wolf was amazed that almost no one under fifty-five showed any signs of heart disease, which at the time was America’s leading cause of death in men under sixty-five. Wolf enlisted the help of John Bruhn, a sociologist. They found that there was no suicide, alcoholism, or drug addiction in Roseto: everyone seemed to be dying of old age. According to Gladwell, Roseto was an outlier.

    Section 2.

    Wolf was forced to rule out diet and lifestyle as explanations, because the Rosetans had poor eating habits, smoked heavily, and were obese. He ruled out genetics after determining that Rosetans’ relatives in other parts of the country were not in comparably good health. Wolf eventually decided that what made Roseto’s inhabitants so healthy was the town itself—its culture and social structure. Many homes contained three generations living together, and with a population of just two thousand people, there were twenty-two separate civic organizations.

    Wolf and Bruhn were met with a great deal of skepticism. They had to work hard to convince the medical establishment that the values of where we live and the people around us have a significant impact on who we are. Gladwell wants Outliers to do for our understanding of success what Wolf did for our understanding of health.

    Summary: Chapter One: The Matthew Effect

    Section 1.

    Gladwell describes a game between two teams in the Canadian Hockey League, the most competitive junior hockey league in the world. Starting at a very young age, players are regularly assessed for talent, so that the best can be separated out and prepared for the next level. The system is designed to be a meritocracy.

    Section 2.

    Gladwell wants to show that circumstances matter just as much for success as work ethic or intelligence. People often ask about the lifestyle, intelligence, or special talents of successful individuals, but not enough people ask when and where a person grew up. Gladwell likens people to trees: we all know that the tallest trees received the most sunlight, had nutrient-rich soil, and were lucky enough to avoid lumberjacks. He suggests that we study the environmental and social influences that make people successful.

    Section 3.

    In the 1980s, Canadian psychologist Roger Barnsley observed that on elite Canadian hockey teams, whether youth league or NHL, a disproportionate number of players have birthdays in the first three months of the year.

    Section 4.

    The explanation for the distribution of birthdays is simple: the cutoff date for an individual’s league assignment is January 1. A player born on January 2 will be 12 months older than one born at the end of December. At the age of nine or ten, this often translates into a huge difference in size, coordination, and maturity. By age ten, coaches regularly pick the oldest and largest potential players for the more competitive “rep squads,” where the players will receive better coaching, have more practice time, and play many more games. By thirteen or fourteen, all of the extra experience and coaching will have actually made the players better, and they will be selected for the more competitive league(s). The same thing happens in American youth baseball and European soccer, but with different cutoff dates.

    The phenomenon is also observable in education. Economists Kelly Bedard and Elizabeth Dhuey found that on math and science tests, the older children in fourth grade regularly score better than the youngest children. This can affect whether a child qualifies for a gifted program. When Bedard and Dhuey extended their analysis to four-year colleges, they found that the students who belonged to the relatively youngest group were underrepresented by more than 10 percent.

    Section 5.

    The top-level hockey players were given opportunities they neither deserved nor earned. Sociologist Robert Merton called this the “Matthew Effect,” after the verse in the Gospel of Matthew:

    “For unto everyone that hath shall be given, and he shall have abundance. But from that hath not shall be taken away even that which he hath.”

    The successful receive more resources: the best students receive the best teaching, the richest citizens get the biggest tax breaks, the largest kids get the best coaching. Sociologists call this “accumulative advantage.” Gladwell points out that cutoff dates exclude nearly half of the potential athletes from a population. Junior hockey teams in the Czech Republic show the same unbalanced distribution of birthdays as in Canada. If Canada or the Czech Republic separated each of their youth leagues into two separate leagues, one for kids born in the first half of the year, and one for kids born in the second half of the year, they would have twice as many athletes available for their national teams. Similarly, schools could separate kindergarten classes into students born in the first, middle, and last four months of the year. The benefits would justify the added administrative work, but, writes Gladwell, the scheme would run afoul of society’s need to believe that individual merit matters more than the rules society has created.

    Section 6.

    Gord Wasden, the father of one of the Canadian Hockey League boys from the first section, describes his son. Scott Wasden worked hard to get where he is, but he has also generally had the advantage of being big compared to others on his team. He was born on January 4.

    Analysis: Introduction: The Roseto Mystery & Chapter 1: The Matthew Effect

    Gladwell's thesis argues that that the idea of rugged, individual success is not accurate. Rather, the most successful person doesn’t thrive without some environmental and social influence plus a dose of good fortune.  After laying out the concepts of a meritocracy and suggesting that this is the way that hockey players advance in Canada, he immediately undercuts this idea. Gladwell uses the illustration of birthday distribution as an example of an invisible contributor to the success of hockey players. With a registration cutoff date of January 1, players born from January 2 through March 31 are older than teammates born later in the year. These older players are likely bigger, faster, more coordinated, and more mature. Since the older players are seen as more skilled, they get selected for more advanced leagues with more practice, more games, and higher-quality coaching. By the time these older players reach their early teens, the extra advantages gained from being judged better because of their birthday translate into being better players. Similarly, the age cutoff for school registrations often mistakes maturity for ability. As a result, the older children appear smarter, get put into advanced groups, and qualify for gifted programs. The birthdate bias carries through to college.

    Advantages result in more advantages. Gladwell reinforces this idea with the “Matthew Effect,” which states that "success leads to more success." More simply: by being a little bit better, a hockey player will get opportunities that may result in the player becoming an outlier. Gladwell implies that the systems that determine success are not efficient. He asks readers to question the way we, as a society, think about success. He suggests that changing the systems in athletics and education would chip away at the myth of individual merit as the chief marker of success and help level the playing field. Gladwell's model for this phenomenon is hockey player Scott Wasden. By demonstrating that Scott had the passion, talent, and work ethic for the game, as well as the good luck to be born on January 4, Gladwell reasons that Wasden, like many others he will be profiling, benefit by being both good and lucky.

    Reference

    • “Outliers Introduction & Chapter 1 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section1/.
    ',27);function u(m,f,y,p,g,b){const t=a;return s(),r("div",null,[d,n(t,{readTime:"8",words:"1.4k"}),c])}const T=o(l,[["render",u]]);export{S as __pageData,T as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as s,c as r,H as n,k as e,a as i,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Introduction & Chapter 1: The Roseto Mystery","description":"Chapter 1 summary clips from Sparknotes of novel Outliers by Malcom Gladwells","frontmatter":{"author":"查尔斯","title":"Introduction & Chapter 1: The Roseto Mystery","description":"Chapter 1 summary clips from Sparknotes of novel Outliers by Malcom Gladwells"},"headers":[],"relativePath":"save/reading/outliers/1.md","filePath":"save/reading/outliers/1.md","lastUpdated":1699051935000}'),l={name:"save/reading/outliers/1.md"},d=e("h1",{id:"introduction-chapter-1-the-roseto-mystery",tabindex:"-1"},[i("Introduction & Chapter 1: The Roseto Mystery "),e("a",{class:"header-anchor",href:"#introduction-chapter-1-the-roseto-mystery","aria-label":'Permalink to "Introduction & Chapter 1: The Roseto Mystery"'},"​")],-1),c=h('

    Summary: Introduction: The Roseto Mystery

    Section 1.

    In the late 1800s, immigrants from Roseto Valfortore, Italy, came to Pennsylvania to work in the slate quarry near the town of Bangor. The settlers established a new community, named after their old one: Roseto. They built schools, a park, small shops, and more than a dozen factories. They kept to themselves and did not interact much with the predominantly German and English populations of the towns around them.

    In the 1950s, a local doctor told Stewart Wolf, a medical researcher, that hardly anyone in Roseto under age sixty-five had heart disease. Wolf was curious. He did blood draws and EKG scans, and he analyzed physicians’ records and death certificates. Wolf was amazed that almost no one under fifty-five showed any signs of heart disease, which at the time was America’s leading cause of death in men under sixty-five. Wolf enlisted the help of John Bruhn, a sociologist. They found that there was no suicide, alcoholism, or drug addiction in Roseto: everyone seemed to be dying of old age. According to Gladwell, Roseto was an outlier.

    Section 2.

    Wolf was forced to rule out diet and lifestyle as explanations, because the Rosetans had poor eating habits, smoked heavily, and were obese. He ruled out genetics after determining that Rosetans’ relatives in other parts of the country were not in comparably good health. Wolf eventually decided that what made Roseto’s inhabitants so healthy was the town itself—its culture and social structure. Many homes contained three generations living together, and with a population of just two thousand people, there were twenty-two separate civic organizations.

    Wolf and Bruhn were met with a great deal of skepticism. They had to work hard to convince the medical establishment that the values of where we live and the people around us have a significant impact on who we are. Gladwell wants Outliers to do for our understanding of success what Wolf did for our understanding of health.

    Summary: Chapter One: The Matthew Effect

    Section 1.

    Gladwell describes a game between two teams in the Canadian Hockey League, the most competitive junior hockey league in the world. Starting at a very young age, players are regularly assessed for talent, so that the best can be separated out and prepared for the next level. The system is designed to be a meritocracy.

    Section 2.

    Gladwell wants to show that circumstances matter just as much for success as work ethic or intelligence. People often ask about the lifestyle, intelligence, or special talents of successful individuals, but not enough people ask when and where a person grew up. Gladwell likens people to trees: we all know that the tallest trees received the most sunlight, had nutrient-rich soil, and were lucky enough to avoid lumberjacks. He suggests that we study the environmental and social influences that make people successful.

    Section 3.

    In the 1980s, Canadian psychologist Roger Barnsley observed that on elite Canadian hockey teams, whether youth league or NHL, a disproportionate number of players have birthdays in the first three months of the year.

    Section 4.

    The explanation for the distribution of birthdays is simple: the cutoff date for an individual’s league assignment is January 1. A player born on January 2 will be 12 months older than one born at the end of December. At the age of nine or ten, this often translates into a huge difference in size, coordination, and maturity. By age ten, coaches regularly pick the oldest and largest potential players for the more competitive “rep squads,” where the players will receive better coaching, have more practice time, and play many more games. By thirteen or fourteen, all of the extra experience and coaching will have actually made the players better, and they will be selected for the more competitive league(s). The same thing happens in American youth baseball and European soccer, but with different cutoff dates.

    The phenomenon is also observable in education. Economists Kelly Bedard and Elizabeth Dhuey found that on math and science tests, the older children in fourth grade regularly score better than the youngest children. This can affect whether a child qualifies for a gifted program. When Bedard and Dhuey extended their analysis to four-year colleges, they found that the students who belonged to the relatively youngest group were underrepresented by more than 10 percent.

    Section 5.

    The top-level hockey players were given opportunities they neither deserved nor earned. Sociologist Robert Merton called this the “Matthew Effect,” after the verse in the Gospel of Matthew:

    “For unto everyone that hath shall be given, and he shall have abundance. But from that hath not shall be taken away even that which he hath.”

    The successful receive more resources: the best students receive the best teaching, the richest citizens get the biggest tax breaks, the largest kids get the best coaching. Sociologists call this “accumulative advantage.” Gladwell points out that cutoff dates exclude nearly half of the potential athletes from a population. Junior hockey teams in the Czech Republic show the same unbalanced distribution of birthdays as in Canada. If Canada or the Czech Republic separated each of their youth leagues into two separate leagues, one for kids born in the first half of the year, and one for kids born in the second half of the year, they would have twice as many athletes available for their national teams. Similarly, schools could separate kindergarten classes into students born in the first, middle, and last four months of the year. The benefits would justify the added administrative work, but, writes Gladwell, the scheme would run afoul of society’s need to believe that individual merit matters more than the rules society has created.

    Section 6.

    Gord Wasden, the father of one of the Canadian Hockey League boys from the first section, describes his son. Scott Wasden worked hard to get where he is, but he has also generally had the advantage of being big compared to others on his team. He was born on January 4.

    Analysis: Introduction: The Roseto Mystery & Chapter 1: The Matthew Effect

    Gladwell's thesis argues that that the idea of rugged, individual success is not accurate. Rather, the most successful person doesn’t thrive without some environmental and social influence plus a dose of good fortune.  After laying out the concepts of a meritocracy and suggesting that this is the way that hockey players advance in Canada, he immediately undercuts this idea. Gladwell uses the illustration of birthday distribution as an example of an invisible contributor to the success of hockey players. With a registration cutoff date of January 1, players born from January 2 through March 31 are older than teammates born later in the year. These older players are likely bigger, faster, more coordinated, and more mature. Since the older players are seen as more skilled, they get selected for more advanced leagues with more practice, more games, and higher-quality coaching. By the time these older players reach their early teens, the extra advantages gained from being judged better because of their birthday translate into being better players. Similarly, the age cutoff for school registrations often mistakes maturity for ability. As a result, the older children appear smarter, get put into advanced groups, and qualify for gifted programs. The birthdate bias carries through to college.

    Advantages result in more advantages. Gladwell reinforces this idea with the “Matthew Effect,” which states that "success leads to more success." More simply: by being a little bit better, a hockey player will get opportunities that may result in the player becoming an outlier. Gladwell implies that the systems that determine success are not efficient. He asks readers to question the way we, as a society, think about success. He suggests that changing the systems in athletics and education would chip away at the myth of individual merit as the chief marker of success and help level the playing field. Gladwell's model for this phenomenon is hockey player Scott Wasden. By demonstrating that Scott had the passion, talent, and work ethic for the game, as well as the good luck to be born on January 4, Gladwell reasons that Wasden, like many others he will be profiling, benefit by being both good and lucky.

    Reference

    • “Outliers Introduction & Chapter 1 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section1/.
    ',27);function u(m,f,y,p,g,b){const t=a;return s(),r("div",null,[d,n(t,{readTime:"8",words:"1.4k"}),c])}const T=o(l,[["render",u]]);export{S as __pageData,T as default}; diff --git a/assets/save_reading_outliers_1.md.64c11331.lean.js b/assets/save_reading_outliers_1.md.9f6d6e06.lean.js similarity index 94% rename from assets/save_reading_outliers_1.md.64c11331.lean.js rename to assets/save_reading_outliers_1.md.9f6d6e06.lean.js index abca223c..61d413eb 100644 --- a/assets/save_reading_outliers_1.md.64c11331.lean.js +++ b/assets/save_reading_outliers_1.md.9f6d6e06.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as s,c as r,H as n,k as e,a as i,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Introduction & Chapter 1: The Roseto Mystery","description":"Chapter 1 summary clips from Sparknotes of novel Outliers by Malcom Gladwells","frontmatter":{"author":"查尔斯","title":"Introduction & Chapter 1: The Roseto Mystery","description":"Chapter 1 summary clips from Sparknotes of novel Outliers by Malcom Gladwells"},"headers":[],"relativePath":"save/reading/outliers/1.md","filePath":"save/reading/outliers/1.md","lastUpdated":1695377563000}'),l={name:"save/reading/outliers/1.md"},d=e("h1",{id:"introduction-chapter-1-the-roseto-mystery",tabindex:"-1"},[i("Introduction & Chapter 1: The Roseto Mystery "),e("a",{class:"header-anchor",href:"#introduction-chapter-1-the-roseto-mystery","aria-label":'Permalink to "Introduction & Chapter 1: The Roseto Mystery"'},"​")],-1),c=h("",27);function u(m,f,y,p,g,b){const t=a;return s(),r("div",null,[d,n(t,{readTime:"8",words:"1.4k"}),c])}const T=o(l,[["render",u]]);export{S as __pageData,T as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as s,c as r,H as n,k as e,a as i,Q as h}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Introduction & Chapter 1: The Roseto Mystery","description":"Chapter 1 summary clips from Sparknotes of novel Outliers by Malcom Gladwells","frontmatter":{"author":"查尔斯","title":"Introduction & Chapter 1: The Roseto Mystery","description":"Chapter 1 summary clips from Sparknotes of novel Outliers by Malcom Gladwells"},"headers":[],"relativePath":"save/reading/outliers/1.md","filePath":"save/reading/outliers/1.md","lastUpdated":1699051935000}'),l={name:"save/reading/outliers/1.md"},d=e("h1",{id:"introduction-chapter-1-the-roseto-mystery",tabindex:"-1"},[i("Introduction & Chapter 1: The Roseto Mystery "),e("a",{class:"header-anchor",href:"#introduction-chapter-1-the-roseto-mystery","aria-label":'Permalink to "Introduction & Chapter 1: The Roseto Mystery"'},"​")],-1),c=h("",27);function u(m,f,y,p,g,b){const t=a;return s(),r("div",null,[d,n(t,{readTime:"8",words:"1.4k"}),c])}const T=o(l,[["render",u]]);export{S as __pageData,T as default}; diff --git a/assets/save_reading_outliers_2.md.74187620.js b/assets/save_reading_outliers_2.md.0f26746f.js similarity index 99% rename from assets/save_reading_outliers_2.md.74187620.js rename to assets/save_reading_outliers_2.md.0f26746f.js index e8882494..063b6707 100644 --- a/assets/save_reading_outliers_2.md.74187620.js +++ b/assets/save_reading_outliers_2.md.0f26746f.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as i,c as r,H as n,k as e,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Chapter Two: The 10,000-Hour Rule","description":"Summary of Chapter Two: The 10,000-Hour Rule of Outliers from Sparknotes","frontmatter":{"title":"Chapter Two: The 10,000-Hour Rule","description":"Summary of Chapter Two: The 10,000-Hour Rule of Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/2.md","filePath":"save/reading/outliers/2.md","lastUpdated":1695377563000}'),h={name:"save/reading/outliers/2.md"},c=e("h1",{id:"chapter-two-the-10-000-hour-rule",tabindex:"-1"},[s("Chapter Two: The 10,000-Hour Rule "),e("a",{class:"header-anchor",href:"#chapter-two-the-10-000-hour-rule","aria-label":'Permalink to "Chapter Two: The 10,000-Hour Rule"'},"​")],-1),d=l('

    Summary: Chapter Two: The 10,000-Hour Rule

    Section 1.

    Bill Joy, a co-founder of Sun Microsystems, is one of the most influential computer programmers of all time. Joy attended the University of Michigan, thinking to become a biologist or mathematician, but he became obsessed with the Computer Center that opened during his freshman year. In 1975, he enrolled in graduate school at UC Berkeley. At both schools, Bill Joy spent much of his free time programming. After graduating from Berkeley, he founded Sun Microsystems, eventually rewriting the Java programming language. He would appear to be a good example of success based on individual merit.

    Section 2.

    If achievement is the combination of talent and preparation, how much does innate talent affect one’s success? In the 1990s, a study at Berlin’s elite Academy of Music determined that, regardless of instrument, all of the world-class students had practiced more than 10,000 hours. They did not find anyone at the top level who spent less time, nor did they find anyone who spent that amount of time who was not successful. Neurologist Daniel Levitin states that, across many fields, world-class expertise is never accomplished in less than 10,000 hours. The law holds even for a prodigy like Mozart, who started composing at age six: he did not compose his first masterwork until he was twenty-one. The youth athletes from the previous chapter who made it to the professional level put in 10,000 hours of practice. And note: individuals cannot normally put in that much practice without help. Most people will need supportive parents, financial stability, and probably a special program—like an all-star youth hockey team.

    Section 3.

    Bill Joy was certainly intelligent, having achieved a perfect score on the math portion of his Scholastic Aptitude Test. His opportunities, however, were extraordinary. Bill Joy happened to choose a college that had a time-sharing computer available, something that was exceedingly rare during the early 1970s. While most students had to pay for computer time, Bill Joy exploited a bug in the college’s system to gain unlimited access to the Computer Center, which was walking distance from where he lived. He was able to spend almost all of his free time programming, and when he went to Berkeley, he had a terminal at home, where he could program until he fell asleep at his keyboard. Bill Joy was able to accumulate 10,000 hours while in college.

    Section 4.

    The Beatles are another example of the 10,000-hours principle. In 1960, when they were still a high school rock band, they were given the chance to travel to Hamburg, Germany and play in various strip clubs. The Beatles were contracted to play for hours every night, seven nights a week, and thereby were forced to develop as musicians. After a year and a half, they had performed 270 nights. By 1964, when they first found commercial success, they had performed an estimated twelve hundred times—more than most band bands do in an entire career.

    Section 5.

    Born in Seattle to affluent parents, Bill Gates was sent to a private school for seventh grade. The school’s Mother’s Club funded the purchase of a time-sharing terminal connected to a mainframe computer in Seattle. As an eighth-grader, Gates was able to start programming. When the Mother’s Club could no longer pay for computing time, Gates was able to continue programming at Information Sciences, Inc. (ISI) through a connection he made with one of the school parents. After that, one of ISI’s founders recommended Gates for a programming project at the Bonneville Power station. Gates was able to leave high school during his senior year to program for the Bonneville Power station as an independent study project. By the time Bill Gates dropped out of Harvard, he was well past 10,000 hours of experience.

    Section 6.

    In a list of the seventy-five richest people in human history, going as far back as ancient Egypt and converting all wealth estimates into modern U.S. dollars, fourteen names are Americans born within nine years of one another (including John D. Rockefeller and J.P. Morgan). What accounts for the fact that a list that covers thousands of years should have 20 percent of its members so close together? The fourteen Americans happened to live during the 1860s and 1870s, when the American economy was undergoing a huge transformation: the expansion of the railroads and the creation of Wall Street. Gladwell argues that the fourteen names are so close in birth date because they were all the perfect age to seize the opportunities available.

    Bill Joy and Bill Gates were also born at just the right time. In 1975, Popular Electronics ran a cover story about the Altair 8800, a $397 microcomputer kit. Someone born before 1954 would likely already have a job with IBM, working on mainframes. Someone born after 1956 would likely still be in high school. Most of the biggest pioneers in the modern computer industry, including Bill Gates, Bill Joy, Steve Jobs, and Eric Schmidt, were born in 1954 or 1955, as were Joy’s three fellow founders at Sun.

    Analysis: Chapter Two: The 10,000-Hour Rule

    Gladwell introduces his controversial and widely disputed 10,000 hours rule. Simply put, the rule suggests that to master a skill, an individual needs to practice it for 10,000 hours. Gladwell argues that, like hockey, success in computing requires both skill and luck, rather than pure, simple, natural ability. Gladwell's example is situated at the University of Michigan, specifically the new computer center, in 1971. The story of Bill Joy undermines the idea of success as an inexplicable, miraculous accomplishment. Though Gladwell agrees Joy is bright and talented, Joy also lucks into several happy accidents that allow for increased access. These strokes of luck give Joy the opportunity to become a computer expert. Gladwell's use of a psychological study conducted at the Academy of Music in Berlin, Germany, in the early 1990s forms the crux of his argument in this chapter. However, critics have suggested that this study was flawed and that there is no incontrovertible evidence to suggest that doing anything for 10,000 hours guarantees mastery. Rather, practice is, as Gladwell points out elsewhere throughout the text, just one of the factors in success. However, he also correlates the familial and economic advantages necessary to reach 10,000 of practice time, reinforcing the larger thesis of the book.

    Gladwell argues that the Beatles and Bill Gates are examples of his notion of time spent directly relating to mastery. While detailing how the Beatles reached the 10,000-hour threshold for mastery, Gladwell also highlights the lucky breaks they had in achieving success, like the connection that landed the band in Hamburg’s music scene. Additionally, while Gates has become something of an American folk hero, Gladwell argues that Gates did not reach his great achievements completely on his own. His wealthy family, his lucky interaction with a computer in 1968, and his college experience allowed him far greater access to opportunity. Without this combination of factors, along with his intelligence and drive, Gates would likely not have become a household name. Again, Gladwell reinforces the idea that success comes not only from being good, but from having no small amount of luck, whether that be time, money, or, in an echo of the hockey player example, birthdate.

    Gladwell claims that one important factor of success is the year in which one is born. In terms of wealth, there are 14 Americans, born in a nine-year period of the 1800s, who are among the richest people in history. This suggests that there was some connection to when they were born and the opportunities available to them in terms of innovation and invention, as well as the position they were in to take advantage of the opportunities. Similarly, men born in the same era of Bill Gates were coming of age at the bleeding edge of technology. Proximity to social and technological change, as well as the wealth and connections to take advantage of it, put these men in an advantageous position. Being in the right place at the right time, Gladwell argues, has at least as much to do with success as one's inborn abilities.

    Reference

    • “Outliers Chapter 2 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section2/. Accessed 27 Feb. 2023.
    ',19);function u(m,p,f,g,y,w){const t=a;return i(),r("div",null,[c,n(t,{readTime:"8",words:"1.4k"}),d])}const T=o(h,[["render",u]]);export{S as __pageData,T as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as i,c as r,H as n,k as e,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Chapter Two: The 10,000-Hour Rule","description":"Summary of Chapter Two: The 10,000-Hour Rule of Outliers from Sparknotes","frontmatter":{"title":"Chapter Two: The 10,000-Hour Rule","description":"Summary of Chapter Two: The 10,000-Hour Rule of Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/2.md","filePath":"save/reading/outliers/2.md","lastUpdated":1699051935000}'),h={name:"save/reading/outliers/2.md"},c=e("h1",{id:"chapter-two-the-10-000-hour-rule",tabindex:"-1"},[s("Chapter Two: The 10,000-Hour Rule "),e("a",{class:"header-anchor",href:"#chapter-two-the-10-000-hour-rule","aria-label":'Permalink to "Chapter Two: The 10,000-Hour Rule"'},"​")],-1),d=l('

    Summary: Chapter Two: The 10,000-Hour Rule

    Section 1.

    Bill Joy, a co-founder of Sun Microsystems, is one of the most influential computer programmers of all time. Joy attended the University of Michigan, thinking to become a biologist or mathematician, but he became obsessed with the Computer Center that opened during his freshman year. In 1975, he enrolled in graduate school at UC Berkeley. At both schools, Bill Joy spent much of his free time programming. After graduating from Berkeley, he founded Sun Microsystems, eventually rewriting the Java programming language. He would appear to be a good example of success based on individual merit.

    Section 2.

    If achievement is the combination of talent and preparation, how much does innate talent affect one’s success? In the 1990s, a study at Berlin’s elite Academy of Music determined that, regardless of instrument, all of the world-class students had practiced more than 10,000 hours. They did not find anyone at the top level who spent less time, nor did they find anyone who spent that amount of time who was not successful. Neurologist Daniel Levitin states that, across many fields, world-class expertise is never accomplished in less than 10,000 hours. The law holds even for a prodigy like Mozart, who started composing at age six: he did not compose his first masterwork until he was twenty-one. The youth athletes from the previous chapter who made it to the professional level put in 10,000 hours of practice. And note: individuals cannot normally put in that much practice without help. Most people will need supportive parents, financial stability, and probably a special program—like an all-star youth hockey team.

    Section 3.

    Bill Joy was certainly intelligent, having achieved a perfect score on the math portion of his Scholastic Aptitude Test. His opportunities, however, were extraordinary. Bill Joy happened to choose a college that had a time-sharing computer available, something that was exceedingly rare during the early 1970s. While most students had to pay for computer time, Bill Joy exploited a bug in the college’s system to gain unlimited access to the Computer Center, which was walking distance from where he lived. He was able to spend almost all of his free time programming, and when he went to Berkeley, he had a terminal at home, where he could program until he fell asleep at his keyboard. Bill Joy was able to accumulate 10,000 hours while in college.

    Section 4.

    The Beatles are another example of the 10,000-hours principle. In 1960, when they were still a high school rock band, they were given the chance to travel to Hamburg, Germany and play in various strip clubs. The Beatles were contracted to play for hours every night, seven nights a week, and thereby were forced to develop as musicians. After a year and a half, they had performed 270 nights. By 1964, when they first found commercial success, they had performed an estimated twelve hundred times—more than most band bands do in an entire career.

    Section 5.

    Born in Seattle to affluent parents, Bill Gates was sent to a private school for seventh grade. The school’s Mother’s Club funded the purchase of a time-sharing terminal connected to a mainframe computer in Seattle. As an eighth-grader, Gates was able to start programming. When the Mother’s Club could no longer pay for computing time, Gates was able to continue programming at Information Sciences, Inc. (ISI) through a connection he made with one of the school parents. After that, one of ISI’s founders recommended Gates for a programming project at the Bonneville Power station. Gates was able to leave high school during his senior year to program for the Bonneville Power station as an independent study project. By the time Bill Gates dropped out of Harvard, he was well past 10,000 hours of experience.

    Section 6.

    In a list of the seventy-five richest people in human history, going as far back as ancient Egypt and converting all wealth estimates into modern U.S. dollars, fourteen names are Americans born within nine years of one another (including John D. Rockefeller and J.P. Morgan). What accounts for the fact that a list that covers thousands of years should have 20 percent of its members so close together? The fourteen Americans happened to live during the 1860s and 1870s, when the American economy was undergoing a huge transformation: the expansion of the railroads and the creation of Wall Street. Gladwell argues that the fourteen names are so close in birth date because they were all the perfect age to seize the opportunities available.

    Bill Joy and Bill Gates were also born at just the right time. In 1975, Popular Electronics ran a cover story about the Altair 8800, a $397 microcomputer kit. Someone born before 1954 would likely already have a job with IBM, working on mainframes. Someone born after 1956 would likely still be in high school. Most of the biggest pioneers in the modern computer industry, including Bill Gates, Bill Joy, Steve Jobs, and Eric Schmidt, were born in 1954 or 1955, as were Joy’s three fellow founders at Sun.

    Analysis: Chapter Two: The 10,000-Hour Rule

    Gladwell introduces his controversial and widely disputed 10,000 hours rule. Simply put, the rule suggests that to master a skill, an individual needs to practice it for 10,000 hours. Gladwell argues that, like hockey, success in computing requires both skill and luck, rather than pure, simple, natural ability. Gladwell's example is situated at the University of Michigan, specifically the new computer center, in 1971. The story of Bill Joy undermines the idea of success as an inexplicable, miraculous accomplishment. Though Gladwell agrees Joy is bright and talented, Joy also lucks into several happy accidents that allow for increased access. These strokes of luck give Joy the opportunity to become a computer expert. Gladwell's use of a psychological study conducted at the Academy of Music in Berlin, Germany, in the early 1990s forms the crux of his argument in this chapter. However, critics have suggested that this study was flawed and that there is no incontrovertible evidence to suggest that doing anything for 10,000 hours guarantees mastery. Rather, practice is, as Gladwell points out elsewhere throughout the text, just one of the factors in success. However, he also correlates the familial and economic advantages necessary to reach 10,000 of practice time, reinforcing the larger thesis of the book.

    Gladwell argues that the Beatles and Bill Gates are examples of his notion of time spent directly relating to mastery. While detailing how the Beatles reached the 10,000-hour threshold for mastery, Gladwell also highlights the lucky breaks they had in achieving success, like the connection that landed the band in Hamburg’s music scene. Additionally, while Gates has become something of an American folk hero, Gladwell argues that Gates did not reach his great achievements completely on his own. His wealthy family, his lucky interaction with a computer in 1968, and his college experience allowed him far greater access to opportunity. Without this combination of factors, along with his intelligence and drive, Gates would likely not have become a household name. Again, Gladwell reinforces the idea that success comes not only from being good, but from having no small amount of luck, whether that be time, money, or, in an echo of the hockey player example, birthdate.

    Gladwell claims that one important factor of success is the year in which one is born. In terms of wealth, there are 14 Americans, born in a nine-year period of the 1800s, who are among the richest people in history. This suggests that there was some connection to when they were born and the opportunities available to them in terms of innovation and invention, as well as the position they were in to take advantage of the opportunities. Similarly, men born in the same era of Bill Gates were coming of age at the bleeding edge of technology. Proximity to social and technological change, as well as the wealth and connections to take advantage of it, put these men in an advantageous position. Being in the right place at the right time, Gladwell argues, has at least as much to do with success as one's inborn abilities.

    Reference

    • “Outliers Chapter 2 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section2/. Accessed 27 Feb. 2023.
    ',19);function u(m,p,f,g,y,w){const t=a;return i(),r("div",null,[c,n(t,{readTime:"8",words:"1.4k"}),d])}const T=o(h,[["render",u]]);export{S as __pageData,T as default}; diff --git a/assets/save_reading_outliers_2.md.74187620.lean.js b/assets/save_reading_outliers_2.md.0f26746f.lean.js similarity index 94% rename from assets/save_reading_outliers_2.md.74187620.lean.js rename to assets/save_reading_outliers_2.md.0f26746f.lean.js index 4c8d9289..b5d2d53b 100644 --- a/assets/save_reading_outliers_2.md.74187620.lean.js +++ b/assets/save_reading_outliers_2.md.0f26746f.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as i,c as r,H as n,k as e,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Chapter Two: The 10,000-Hour Rule","description":"Summary of Chapter Two: The 10,000-Hour Rule of Outliers from Sparknotes","frontmatter":{"title":"Chapter Two: The 10,000-Hour Rule","description":"Summary of Chapter Two: The 10,000-Hour Rule of Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/2.md","filePath":"save/reading/outliers/2.md","lastUpdated":1695377563000}'),h={name:"save/reading/outliers/2.md"},c=e("h1",{id:"chapter-two-the-10-000-hour-rule",tabindex:"-1"},[s("Chapter Two: The 10,000-Hour Rule "),e("a",{class:"header-anchor",href:"#chapter-two-the-10-000-hour-rule","aria-label":'Permalink to "Chapter Two: The 10,000-Hour Rule"'},"​")],-1),d=l("",19);function u(m,p,f,g,y,w){const t=a;return i(),r("div",null,[c,n(t,{readTime:"8",words:"1.4k"}),d])}const T=o(h,[["render",u]]);export{S as __pageData,T as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as i,c as r,H as n,k as e,a as s,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const S=JSON.parse('{"title":"Chapter Two: The 10,000-Hour Rule","description":"Summary of Chapter Two: The 10,000-Hour Rule of Outliers from Sparknotes","frontmatter":{"title":"Chapter Two: The 10,000-Hour Rule","description":"Summary of Chapter Two: The 10,000-Hour Rule of Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/2.md","filePath":"save/reading/outliers/2.md","lastUpdated":1699051935000}'),h={name:"save/reading/outliers/2.md"},c=e("h1",{id:"chapter-two-the-10-000-hour-rule",tabindex:"-1"},[s("Chapter Two: The 10,000-Hour Rule "),e("a",{class:"header-anchor",href:"#chapter-two-the-10-000-hour-rule","aria-label":'Permalink to "Chapter Two: The 10,000-Hour Rule"'},"​")],-1),d=l("",19);function u(m,p,f,g,y,w){const t=a;return i(),r("div",null,[c,n(t,{readTime:"8",words:"1.4k"}),d])}const T=o(h,[["render",u]]);export{S as __pageData,T as default}; diff --git a/assets/save_reading_outliers_3.md.0cab1bb8.js b/assets/save_reading_outliers_3.md.ea35e051.js similarity index 99% rename from assets/save_reading_outliers_3.md.0cab1bb8.js rename to assets/save_reading_outliers_3.md.ea35e051.js index bb17d0a6..8a6323c8 100644 --- a/assets/save_reading_outliers_3.md.0cab1bb8.js +++ b/assets/save_reading_outliers_3.md.ea35e051.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as s,o,c as i,H as n,k as e,a as r,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Chapter 3: The Trouble with Geniuses, Part 1","description":"Chapter 3 summary of novel Outliers from Sparknotes","frontmatter":{"title":"Chapter 3: The Trouble with Geniuses, Part 1","description":"Chapter 3 summary of novel Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/3.md","filePath":"save/reading/outliers/3.md","lastUpdated":1695377563000}'),h={name:"save/reading/outliers/3.md"},c=e("h1",{id:"chapter-3-the-trouble-with-geniuses-part-1",tabindex:"-1"},[r("Chapter 3: The Trouble with Geniuses, Part 1 "),e("a",{class:"header-anchor",href:"#chapter-3-the-trouble-with-geniuses-part-1","aria-label":'Permalink to "Chapter 3: The Trouble with Geniuses, Part 1"'},"​")],-1),d=l('

    Summary: Chapter Three: The Trouble with Geniuses, Part 1

    Section 1.

    Chris Langan appeared on the television trivia show 1 vs. 100 after being the subject of interviews and at least one documentary, due to his extremely high IQ. He had little difficulty in high school, got a perfect score on his SAT, and read through Principia Mathematica as a teenager. On 1 vs. 100, Langan cashed out with winnings of $250,000.

    Section 2.

    Shortly after World War I, Lewis Terman, creator of the widely used Stanford-Binet IQ test, became fascinated with child prodigies. In 1921, he identified exceptionally gifted 1,470 students who came to be known as the “Termites.” Terman kept track of them over the years, carefully cataloging their educational achievement, marriages, psychological health, and employment. Terman was sure that the Termites would be the future elite of the United States. The same confidence underlies the use of IQ-like tests, such as the SAT, to assess applicants at Ivy League schools and corporations such as Microsoft and Google. Gladwell states that Terman was wrong about the Termites, and if he had met Chris Langan as a teenager, he would have been wrong about him, too.

    Section 3.

    Gladwell gives two examples—one easy and one much harder—of questions that use visual puzzles to test IQ, without requiring any language abilities or specific factual knowledge. The average human will score 100. Those scoring below 70 are considered mentally disabled, and those who are successful in graduate programs likely have an IQ of 115 or higher. According to Gladwell, however, above 120 IQ makes little or no difference to success. A similar point applies to basketball: height is certainly an advantage, but there is, at best, modest value in being six foot seven instead of six foot six. A basketball player just needs to be tall enough.

    A list of the last twenty-five Americans to win a Nobel Prize in Medicine includes graduates of prestigious schools, such as Columbia, Harvard, and MIT, but also graduates of DePauw, Holy Cross, and Gettysburg College. Similarly, there have been American Nobel laureates in Chemistry from Harvard and MIT, but also from Notre Dame and the University of Illinois. Harvard might have more intelligent students, but many other colleges have students smart enough to win a Nobel.

    At the University of Michigan law school, around 10 percent of students are racial minorities. Without affirmative action, there would be less than 3 percent. Looking at career performance after graduation, Michigan found no difference between white and minority graduates. Minority students come into law school with weaker academic credentials than their white counterparts, but they are above the threshold required to be just as successful.

    Section 4.

    Not all questions that test for intelligence have a single correct answer. A different sort of question might ask for a list of different uses for a brick, or a blanket. A question like this measures imagination and creativity. At a top British high school, one student lists more than ten uses, many of which are comical. Another student, a prodigy with one of the school’s highest IQs, lists just a few uses, all of which are practical. Compared to an IQ test, asking about different uses for a brick might be a better way to identify future Nobel Prize winners.

    Section 5.

    Terman’s error was using intelligence alone to choose his Termites. While some of the Termites had successful careers, an unexpectedly high went on to careers that even Terman didn’t consider to be successful. The two students tested by Terman’s team who actually did go on to win Nobels were not selected as Termites: their IQs were too low. Terman eventually concluded that “intellect and achievement are far from perfectly correlated.”

    Gladwell states that to understand Chris Langan’s prospects of becoming a “true outlier,” one must learn more about him.

    Analysis: Chapter Three: The Trouble with Geniuses, Part 1

    Intelligence, Gladwell argues, does not equal success. He dedicates this chapter to the examination of geniuses. Comparing the young subjects of Lewis Terman to Chris Langan, Gladwell argues against Terman’s idea that genius is a key to societal advancement. Gladwell lists Langan’s early accomplishments as a shining example of Terman's idea, then swiftly undercuts expectations. Gladwell argues again that individuals do not succeed or fail solely on their own, but rather due to a constellation of factors, many of which are uncontrollable. Langan's early achievements would suggest great things and a continued path toward accomplishment, but Gladwell includes the anecdote of his game show appearance to undermine the notion that genius equals success. Using two questions from an IQ test, Gladwell introduces the idea of an IQ threshold to examine the the larger notion of intelligence and its limitations. Arguing that the measure of someone’s intelligence is only helpful up to a point, Gladwell uses examples of schools that Nobel laureates attended for undergraduate studies. Some, he points out, are elite institutions; others are not. Additionally, he points to success among graduates of the law school at the University of Michigan. There was no quantifiable difference in success post-graduation between white and POC students, some of whom were admitted under affirmative action with slightly lower undergraduate grades and standardized test scores. Reasonably, then, the level of intelligence beyond a certain point is moot. All of the students were intelligent enough to graduate, and beyond that, he argues, their intelligence predicted nothing.

    Elements other than intelligence must contribute to success. Gladwell expands on his notion of an intelligence threshold and examines these other factors through an example of a question on a divergence test. Using examples of two students at an elite British school, Gladwell shows that the divergence test has no right answers, but instead looks for answers that demonstrate uniqueness and creativity. Intelligence matters, but so does imagination, creativity, and outside-the-box thinking. Gladwell circles back to Terman, reinforcing that the error when choosing his Termites was a focus on intelligence alone. He once again turns his attention to Chris Langan, foreshadowing that Langan’s story did not follow a direct line to achievement. Intelligence alone does not offer a certain path to success.

    Reference

    • “Outliers Chapter 3 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section3/. Accessed 27 Feb. 2023.
    ',18);function u(m,g,f,p,w,b){const t=a;return o(),i("div",null,[c,n(t,{readTime:"6",words:"1.1k"}),d])}const _=s(h,[["render",u]]);export{k as __pageData,_ as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as s,o,c as i,H as n,k as e,a as r,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Chapter 3: The Trouble with Geniuses, Part 1","description":"Chapter 3 summary of novel Outliers from Sparknotes","frontmatter":{"title":"Chapter 3: The Trouble with Geniuses, Part 1","description":"Chapter 3 summary of novel Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/3.md","filePath":"save/reading/outliers/3.md","lastUpdated":1699051935000}'),h={name:"save/reading/outliers/3.md"},c=e("h1",{id:"chapter-3-the-trouble-with-geniuses-part-1",tabindex:"-1"},[r("Chapter 3: The Trouble with Geniuses, Part 1 "),e("a",{class:"header-anchor",href:"#chapter-3-the-trouble-with-geniuses-part-1","aria-label":'Permalink to "Chapter 3: The Trouble with Geniuses, Part 1"'},"​")],-1),d=l('

    Summary: Chapter Three: The Trouble with Geniuses, Part 1

    Section 1.

    Chris Langan appeared on the television trivia show 1 vs. 100 after being the subject of interviews and at least one documentary, due to his extremely high IQ. He had little difficulty in high school, got a perfect score on his SAT, and read through Principia Mathematica as a teenager. On 1 vs. 100, Langan cashed out with winnings of $250,000.

    Section 2.

    Shortly after World War I, Lewis Terman, creator of the widely used Stanford-Binet IQ test, became fascinated with child prodigies. In 1921, he identified exceptionally gifted 1,470 students who came to be known as the “Termites.” Terman kept track of them over the years, carefully cataloging their educational achievement, marriages, psychological health, and employment. Terman was sure that the Termites would be the future elite of the United States. The same confidence underlies the use of IQ-like tests, such as the SAT, to assess applicants at Ivy League schools and corporations such as Microsoft and Google. Gladwell states that Terman was wrong about the Termites, and if he had met Chris Langan as a teenager, he would have been wrong about him, too.

    Section 3.

    Gladwell gives two examples—one easy and one much harder—of questions that use visual puzzles to test IQ, without requiring any language abilities or specific factual knowledge. The average human will score 100. Those scoring below 70 are considered mentally disabled, and those who are successful in graduate programs likely have an IQ of 115 or higher. According to Gladwell, however, above 120 IQ makes little or no difference to success. A similar point applies to basketball: height is certainly an advantage, but there is, at best, modest value in being six foot seven instead of six foot six. A basketball player just needs to be tall enough.

    A list of the last twenty-five Americans to win a Nobel Prize in Medicine includes graduates of prestigious schools, such as Columbia, Harvard, and MIT, but also graduates of DePauw, Holy Cross, and Gettysburg College. Similarly, there have been American Nobel laureates in Chemistry from Harvard and MIT, but also from Notre Dame and the University of Illinois. Harvard might have more intelligent students, but many other colleges have students smart enough to win a Nobel.

    At the University of Michigan law school, around 10 percent of students are racial minorities. Without affirmative action, there would be less than 3 percent. Looking at career performance after graduation, Michigan found no difference between white and minority graduates. Minority students come into law school with weaker academic credentials than their white counterparts, but they are above the threshold required to be just as successful.

    Section 4.

    Not all questions that test for intelligence have a single correct answer. A different sort of question might ask for a list of different uses for a brick, or a blanket. A question like this measures imagination and creativity. At a top British high school, one student lists more than ten uses, many of which are comical. Another student, a prodigy with one of the school’s highest IQs, lists just a few uses, all of which are practical. Compared to an IQ test, asking about different uses for a brick might be a better way to identify future Nobel Prize winners.

    Section 5.

    Terman’s error was using intelligence alone to choose his Termites. While some of the Termites had successful careers, an unexpectedly high went on to careers that even Terman didn’t consider to be successful. The two students tested by Terman’s team who actually did go on to win Nobels were not selected as Termites: their IQs were too low. Terman eventually concluded that “intellect and achievement are far from perfectly correlated.”

    Gladwell states that to understand Chris Langan’s prospects of becoming a “true outlier,” one must learn more about him.

    Analysis: Chapter Three: The Trouble with Geniuses, Part 1

    Intelligence, Gladwell argues, does not equal success. He dedicates this chapter to the examination of geniuses. Comparing the young subjects of Lewis Terman to Chris Langan, Gladwell argues against Terman’s idea that genius is a key to societal advancement. Gladwell lists Langan’s early accomplishments as a shining example of Terman's idea, then swiftly undercuts expectations. Gladwell argues again that individuals do not succeed or fail solely on their own, but rather due to a constellation of factors, many of which are uncontrollable. Langan's early achievements would suggest great things and a continued path toward accomplishment, but Gladwell includes the anecdote of his game show appearance to undermine the notion that genius equals success. Using two questions from an IQ test, Gladwell introduces the idea of an IQ threshold to examine the the larger notion of intelligence and its limitations. Arguing that the measure of someone’s intelligence is only helpful up to a point, Gladwell uses examples of schools that Nobel laureates attended for undergraduate studies. Some, he points out, are elite institutions; others are not. Additionally, he points to success among graduates of the law school at the University of Michigan. There was no quantifiable difference in success post-graduation between white and POC students, some of whom were admitted under affirmative action with slightly lower undergraduate grades and standardized test scores. Reasonably, then, the level of intelligence beyond a certain point is moot. All of the students were intelligent enough to graduate, and beyond that, he argues, their intelligence predicted nothing.

    Elements other than intelligence must contribute to success. Gladwell expands on his notion of an intelligence threshold and examines these other factors through an example of a question on a divergence test. Using examples of two students at an elite British school, Gladwell shows that the divergence test has no right answers, but instead looks for answers that demonstrate uniqueness and creativity. Intelligence matters, but so does imagination, creativity, and outside-the-box thinking. Gladwell circles back to Terman, reinforcing that the error when choosing his Termites was a focus on intelligence alone. He once again turns his attention to Chris Langan, foreshadowing that Langan’s story did not follow a direct line to achievement. Intelligence alone does not offer a certain path to success.

    Reference

    • “Outliers Chapter 3 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section3/. Accessed 27 Feb. 2023.
    ',18);function u(m,g,f,p,w,b){const t=a;return o(),i("div",null,[c,n(t,{readTime:"6",words:"1.1k"}),d])}const _=s(h,[["render",u]]);export{k as __pageData,_ as default}; diff --git a/assets/save_reading_outliers_3.md.0cab1bb8.lean.js b/assets/save_reading_outliers_3.md.ea35e051.lean.js similarity index 94% rename from assets/save_reading_outliers_3.md.0cab1bb8.lean.js rename to assets/save_reading_outliers_3.md.ea35e051.lean.js index ac6475d4..7c309e6d 100644 --- a/assets/save_reading_outliers_3.md.0cab1bb8.lean.js +++ b/assets/save_reading_outliers_3.md.ea35e051.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as s,o,c as i,H as n,k as e,a as r,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Chapter 3: The Trouble with Geniuses, Part 1","description":"Chapter 3 summary of novel Outliers from Sparknotes","frontmatter":{"title":"Chapter 3: The Trouble with Geniuses, Part 1","description":"Chapter 3 summary of novel Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/3.md","filePath":"save/reading/outliers/3.md","lastUpdated":1695377563000}'),h={name:"save/reading/outliers/3.md"},c=e("h1",{id:"chapter-3-the-trouble-with-geniuses-part-1",tabindex:"-1"},[r("Chapter 3: The Trouble with Geniuses, Part 1 "),e("a",{class:"header-anchor",href:"#chapter-3-the-trouble-with-geniuses-part-1","aria-label":'Permalink to "Chapter 3: The Trouble with Geniuses, Part 1"'},"​")],-1),d=l("",18);function u(m,g,f,p,w,b){const t=a;return o(),i("div",null,[c,n(t,{readTime:"6",words:"1.1k"}),d])}const _=s(h,[["render",u]]);export{k as __pageData,_ as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as s,o,c as i,H as n,k as e,a as r,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const k=JSON.parse('{"title":"Chapter 3: The Trouble with Geniuses, Part 1","description":"Chapter 3 summary of novel Outliers from Sparknotes","frontmatter":{"title":"Chapter 3: The Trouble with Geniuses, Part 1","description":"Chapter 3 summary of novel Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/3.md","filePath":"save/reading/outliers/3.md","lastUpdated":1699051935000}'),h={name:"save/reading/outliers/3.md"},c=e("h1",{id:"chapter-3-the-trouble-with-geniuses-part-1",tabindex:"-1"},[r("Chapter 3: The Trouble with Geniuses, Part 1 "),e("a",{class:"header-anchor",href:"#chapter-3-the-trouble-with-geniuses-part-1","aria-label":'Permalink to "Chapter 3: The Trouble with Geniuses, Part 1"'},"​")],-1),d=l("",18);function u(m,g,f,p,w,b){const t=a;return o(),i("div",null,[c,n(t,{readTime:"6",words:"1.1k"}),d])}const _=s(h,[["render",u]]);export{k as __pageData,_ as default}; diff --git a/assets/save_reading_outliers_4.md.d65868f7.js b/assets/save_reading_outliers_4.md.8f24b5aa.js similarity index 99% rename from assets/save_reading_outliers_4.md.d65868f7.js rename to assets/save_reading_outliers_4.md.8f24b5aa.js index 58c5fe6d..c65d05cd 100644 --- a/assets/save_reading_outliers_4.md.d65868f7.js +++ b/assets/save_reading_outliers_4.md.8f24b5aa.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as i,H as s,k as e,a as r,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Chapter 4: The Trouble with Geniuses, Part 2","description":"Chapter 4 summary of novel Outliers from Sparknotes","frontmatter":{"title":"Chapter 4: The Trouble with Geniuses, Part 2","description":"Chapter 4 summary of novel Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/4.md","filePath":"save/reading/outliers/4.md","lastUpdated":1695377563000}'),h={name:"save/reading/outliers/4.md"},c=e("h1",{id:"chapter-4-the-trouble-with-geniuses-part-2",tabindex:"-1"},[r("Chapter 4: The Trouble with Geniuses, Part 2 "),e("a",{class:"header-anchor",href:"#chapter-4-the-trouble-with-geniuses-part-2","aria-label":'Permalink to "Chapter 4: The Trouble with Geniuses, Part 2"'},"​")],-1),d=l('

    Summary: Chapter Four: The Trouble with Geniuses, Part 2

    Section 1.

    Chris Langan’s mother had four children, all from different fathers. Her first husband died in Mexico, the second was murdered, the third committed suicide, and the fourth was an abusive alcoholic. Langan says he has never met someone who grew up as impoverished as he and his brothers did. Attending Reed College, in Oregon, on a scholarship, he felt as though he did not belong with the rest of the students. When his mother neglected to fill out the financial aid forms, he lost his scholarship and dropped out. According to Langan, the school just did not care about their students. Later, Langan attended Montana State University in Bozeman but he dropped out when a dean refused Langan’s request to adjust his class schedule because of car trouble. He still has intellectual interests and has been working on a treatise called the “Cognitive Theoretic Model of the Universe.” When asked if, hypothetically, he would take a position at Harvard, he acknowledges the benefit of an environment with so much intellectual energy, but he worries about a lack of intellectual freedom.

    Section 2.

    Gladwell points out the oddity of Langan’s experiences. Most colleges, especially small ones, try to accommodate student needs. Smart people take positions at places like Harvard instead of in the private sector precisely for the added intellectual freedom. Gladwell contrasts Langan’s story with Robert Oppenheimer’s. While at Cambridge, Oppenheimer became frustrated with his tutor and tried to poison him. After negotiations with the school administration, Oppenheimer was put on probation and assigned to a psychiatrist. Whereas Langan dropped out after his mother failed to fill out paperwork, Oppenheimer managed to stay in college after trying to kill someone. Later, Oppenheimer convinced General Leslie Groves to make Oppenheimer the scientific director of the Manhattan Project. Oppenheimer had the ability to persuade people, where Langan did not.

    Section 3.

    Psychologist Robert Sternberg calls the ability to persuade someone “practical intelligence.” It involves knowing what to say, how to say it, and when. It requires an ability to read situations. Individuals can have either practical or analytical intelligence, or in the case of Oppenheimer, both. To understand where one obtains practical intelligence, Gladwell refers to a study conducted by Annette Lareau.

    Lareau observed parenting strategies in both Black and white families from different socioeconomic strata. She found two distinct strategies: “concerted cultivation” and “accomplishment of natural growth.” Concerted cultivation, most common in middle-class and wealthier families, is defined by parents’ active promotion of their children’s talents and interests. Accomplishment of natural growth, most common in working-class or impoverished families, is defined by parents’ lack of interest or interaction in their children’s free time. Concerted cultivation, writes Gladwell, encourages children to seek opportunities for growth and to advocate for themselves. Accomplishment of natural growth leaves children unprepared to shape their environment for their own benefit. Concerted cultivation fosters an attitude better suited for success in the modern world.

    Section 4.

    Oppenheimer was raised by affluent parents who sent him to a progressive private school and took an active interest in his hobbies.

    • Affluent: Having an abundant supply of money or possessions of value.

    By contrast, Chris Langan’s brother Mark states that as children, they learned to resent authority. Mark, too, was unable to obtain financial aid, because he had no knowledge of how the system worked. If Chris Langan had been raised in a family that valued education, he probably would have had more success.

    Section 5.

    Once the Termites reached working adulthood, Terman grouped 730 of the males into three categories, based on their levels of success. The top 20 percent were upper-class professionals, while the bottom 20 percent had low-paying jobs or were unemployed. After analyzing the differences between the groups, Terman found that the bottom 20 percent came almost entirely from the lowest social and economic classes. What they lacked was “a community around them that prepared them properly for the world.”

    Section 6.

    Chris Langan lives on a horse farm in Missouri, where he still writes. He is happily married and continues to read physics and philosophy. While he has spent decades on his writing, almost none of it has ever been published. Langan admits he has not tried to contact publishers or found an agent—and does not plan to. Chris Langan did not have the support necessary to meet success. Gladwell points that no one ever makes it alone, regardless of if they are successful musicians, athletes, tech billionaires, or geniuses.

    Analysis: Chapter Four: The Trouble with Geniuses, Part 2

    Family background plays a crucial role in an individual’s success. While a genius like Chris Langan should thrive on a college campus, he drops out. Langan doesn’t struggle with academics, but with paperwork, procedures, and environment. Gladwell’s characterization of Langan almost makes him seem like two separate characters: a confident, genius game show contestant versus a child from a poor and troubled family. Langan may be a true outlier in the sense that he doesn’t seem to fit in academia or the working-class world.  Langan’s story is ironic. His brilliant mind should propel him to success. However, his story also perfectly proves Gladwell’s point that brainpower alone does not lead to success. The author delves deeper into the irony of Langan’s situation by comparing him to Robert Oppenheimer, who worked on the nuclear bomb during World War II. Like Langan, Oppenheimer possesses great intelligence. Unlike Langan, Oppenheimer has an understanding that allows him to navigate the world effectively. Oppenheimer knows how to combat challenges, where Langan gets bested by a financial aid problem and class schedule. Oppenheimer’s family background gave him the confidence to deal with authority while Langan’s upbringing created a distrust of authority. Without a family background that encourages success, intelligence is not enough.

    Contrast & Comparison

    Oppenheimer’s family background gave him the confidence to deal with authority while Langan’s upbringing created a distrust of authority.

    The power of persuasion is an important factor that drives success. Gladwell notes that the power of persuasion is practical intelligence. He contrasts practical intelligence with analytical ability, noting that just because a person is smart does not mean they have practical intelligence. These two types of knowledge are not necessarily coeval. He reinforces this point with a return to the comparison of Langan and Oppenheimer. Both men are exceedingly intelligent, but Langan lacks the social savvy of practical intelligence. Gladwell suggests that individuals gain practical intelligence skills from their families, discussing a study by sociologist Annette Lareau to prove his point. Children from wealthier families learn how to interact with society in a way that drives achievement. Successful people have the power of persuasion and can convince others to see things from their point of view.

    Success, then, depends on more than individual effort. Gladwell builds this argument by detailing the differences between Oppenheimer’s upbringing and Langan’s. Oppenheimer lived in an upper-class neighborhood with myriad advantages. He learned how to negotiate and stand up for himself. Langan’s family moved from place to place, struggling for jobs, money, food, and clothes, and Langan learned that he couldn’t rely on others. Gladwell's consideration of the Termites' success or struggles as adults supports his assertion that success is more than an individual effort; Gladwell states, “In the end, only one thing mattered: family background.” Terman’s findings and Gladwell’s conclusion do not mean that talented individuals from lower social and economic classes cannot have successful futures. To succeed, everyone needs help along the way, if not from family, then from a supportive community. Individuals do not achieve success solely on their own.

    Reference

    • “Outliers Chapter 4 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section4/.
    ',22);function u(p,m,f,g,w,b){const t=a;return n(),i("div",null,[c,s(t,{readTime:"8",words:"1.3k"}),d])}const T=o(h,[["render",u]]);export{L as __pageData,T as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as i,H as s,k as e,a as r,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Chapter 4: The Trouble with Geniuses, Part 2","description":"Chapter 4 summary of novel Outliers from Sparknotes","frontmatter":{"title":"Chapter 4: The Trouble with Geniuses, Part 2","description":"Chapter 4 summary of novel Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/4.md","filePath":"save/reading/outliers/4.md","lastUpdated":1699051935000}'),h={name:"save/reading/outliers/4.md"},c=e("h1",{id:"chapter-4-the-trouble-with-geniuses-part-2",tabindex:"-1"},[r("Chapter 4: The Trouble with Geniuses, Part 2 "),e("a",{class:"header-anchor",href:"#chapter-4-the-trouble-with-geniuses-part-2","aria-label":'Permalink to "Chapter 4: The Trouble with Geniuses, Part 2"'},"​")],-1),d=l('

    Summary: Chapter Four: The Trouble with Geniuses, Part 2

    Section 1.

    Chris Langan’s mother had four children, all from different fathers. Her first husband died in Mexico, the second was murdered, the third committed suicide, and the fourth was an abusive alcoholic. Langan says he has never met someone who grew up as impoverished as he and his brothers did. Attending Reed College, in Oregon, on a scholarship, he felt as though he did not belong with the rest of the students. When his mother neglected to fill out the financial aid forms, he lost his scholarship and dropped out. According to Langan, the school just did not care about their students. Later, Langan attended Montana State University in Bozeman but he dropped out when a dean refused Langan’s request to adjust his class schedule because of car trouble. He still has intellectual interests and has been working on a treatise called the “Cognitive Theoretic Model of the Universe.” When asked if, hypothetically, he would take a position at Harvard, he acknowledges the benefit of an environment with so much intellectual energy, but he worries about a lack of intellectual freedom.

    Section 2.

    Gladwell points out the oddity of Langan’s experiences. Most colleges, especially small ones, try to accommodate student needs. Smart people take positions at places like Harvard instead of in the private sector precisely for the added intellectual freedom. Gladwell contrasts Langan’s story with Robert Oppenheimer’s. While at Cambridge, Oppenheimer became frustrated with his tutor and tried to poison him. After negotiations with the school administration, Oppenheimer was put on probation and assigned to a psychiatrist. Whereas Langan dropped out after his mother failed to fill out paperwork, Oppenheimer managed to stay in college after trying to kill someone. Later, Oppenheimer convinced General Leslie Groves to make Oppenheimer the scientific director of the Manhattan Project. Oppenheimer had the ability to persuade people, where Langan did not.

    Section 3.

    Psychologist Robert Sternberg calls the ability to persuade someone “practical intelligence.” It involves knowing what to say, how to say it, and when. It requires an ability to read situations. Individuals can have either practical or analytical intelligence, or in the case of Oppenheimer, both. To understand where one obtains practical intelligence, Gladwell refers to a study conducted by Annette Lareau.

    Lareau observed parenting strategies in both Black and white families from different socioeconomic strata. She found two distinct strategies: “concerted cultivation” and “accomplishment of natural growth.” Concerted cultivation, most common in middle-class and wealthier families, is defined by parents’ active promotion of their children’s talents and interests. Accomplishment of natural growth, most common in working-class or impoverished families, is defined by parents’ lack of interest or interaction in their children’s free time. Concerted cultivation, writes Gladwell, encourages children to seek opportunities for growth and to advocate for themselves. Accomplishment of natural growth leaves children unprepared to shape their environment for their own benefit. Concerted cultivation fosters an attitude better suited for success in the modern world.

    Section 4.

    Oppenheimer was raised by affluent parents who sent him to a progressive private school and took an active interest in his hobbies.

    • Affluent: Having an abundant supply of money or possessions of value.

    By contrast, Chris Langan’s brother Mark states that as children, they learned to resent authority. Mark, too, was unable to obtain financial aid, because he had no knowledge of how the system worked. If Chris Langan had been raised in a family that valued education, he probably would have had more success.

    Section 5.

    Once the Termites reached working adulthood, Terman grouped 730 of the males into three categories, based on their levels of success. The top 20 percent were upper-class professionals, while the bottom 20 percent had low-paying jobs or were unemployed. After analyzing the differences between the groups, Terman found that the bottom 20 percent came almost entirely from the lowest social and economic classes. What they lacked was “a community around them that prepared them properly for the world.”

    Section 6.

    Chris Langan lives on a horse farm in Missouri, where he still writes. He is happily married and continues to read physics and philosophy. While he has spent decades on his writing, almost none of it has ever been published. Langan admits he has not tried to contact publishers or found an agent—and does not plan to. Chris Langan did not have the support necessary to meet success. Gladwell points that no one ever makes it alone, regardless of if they are successful musicians, athletes, tech billionaires, or geniuses.

    Analysis: Chapter Four: The Trouble with Geniuses, Part 2

    Family background plays a crucial role in an individual’s success. While a genius like Chris Langan should thrive on a college campus, he drops out. Langan doesn’t struggle with academics, but with paperwork, procedures, and environment. Gladwell’s characterization of Langan almost makes him seem like two separate characters: a confident, genius game show contestant versus a child from a poor and troubled family. Langan may be a true outlier in the sense that he doesn’t seem to fit in academia or the working-class world.  Langan’s story is ironic. His brilliant mind should propel him to success. However, his story also perfectly proves Gladwell’s point that brainpower alone does not lead to success. The author delves deeper into the irony of Langan’s situation by comparing him to Robert Oppenheimer, who worked on the nuclear bomb during World War II. Like Langan, Oppenheimer possesses great intelligence. Unlike Langan, Oppenheimer has an understanding that allows him to navigate the world effectively. Oppenheimer knows how to combat challenges, where Langan gets bested by a financial aid problem and class schedule. Oppenheimer’s family background gave him the confidence to deal with authority while Langan’s upbringing created a distrust of authority. Without a family background that encourages success, intelligence is not enough.

    Contrast & Comparison

    Oppenheimer’s family background gave him the confidence to deal with authority while Langan’s upbringing created a distrust of authority.

    The power of persuasion is an important factor that drives success. Gladwell notes that the power of persuasion is practical intelligence. He contrasts practical intelligence with analytical ability, noting that just because a person is smart does not mean they have practical intelligence. These two types of knowledge are not necessarily coeval. He reinforces this point with a return to the comparison of Langan and Oppenheimer. Both men are exceedingly intelligent, but Langan lacks the social savvy of practical intelligence. Gladwell suggests that individuals gain practical intelligence skills from their families, discussing a study by sociologist Annette Lareau to prove his point. Children from wealthier families learn how to interact with society in a way that drives achievement. Successful people have the power of persuasion and can convince others to see things from their point of view.

    Success, then, depends on more than individual effort. Gladwell builds this argument by detailing the differences between Oppenheimer’s upbringing and Langan’s. Oppenheimer lived in an upper-class neighborhood with myriad advantages. He learned how to negotiate and stand up for himself. Langan’s family moved from place to place, struggling for jobs, money, food, and clothes, and Langan learned that he couldn’t rely on others. Gladwell's consideration of the Termites' success or struggles as adults supports his assertion that success is more than an individual effort; Gladwell states, “In the end, only one thing mattered: family background.” Terman’s findings and Gladwell’s conclusion do not mean that talented individuals from lower social and economic classes cannot have successful futures. To succeed, everyone needs help along the way, if not from family, then from a supportive community. Individuals do not achieve success solely on their own.

    Reference

    • “Outliers Chapter 4 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section4/.
    ',22);function u(p,m,f,g,w,b){const t=a;return n(),i("div",null,[c,s(t,{readTime:"8",words:"1.3k"}),d])}const T=o(h,[["render",u]]);export{L as __pageData,T as default}; diff --git a/assets/save_reading_outliers_4.md.d65868f7.lean.js b/assets/save_reading_outliers_4.md.8f24b5aa.lean.js similarity index 94% rename from assets/save_reading_outliers_4.md.d65868f7.lean.js rename to assets/save_reading_outliers_4.md.8f24b5aa.lean.js index 30f28366..2a183ba9 100644 --- a/assets/save_reading_outliers_4.md.d65868f7.lean.js +++ b/assets/save_reading_outliers_4.md.8f24b5aa.lean.js @@ -1 +1 @@ -import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as i,H as s,k as e,a as r,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Chapter 4: The Trouble with Geniuses, Part 2","description":"Chapter 4 summary of novel Outliers from Sparknotes","frontmatter":{"title":"Chapter 4: The Trouble with Geniuses, Part 2","description":"Chapter 4 summary of novel Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/4.md","filePath":"save/reading/outliers/4.md","lastUpdated":1695377563000}'),h={name:"save/reading/outliers/4.md"},c=e("h1",{id:"chapter-4-the-trouble-with-geniuses-part-2",tabindex:"-1"},[r("Chapter 4: The Trouble with Geniuses, Part 2 "),e("a",{class:"header-anchor",href:"#chapter-4-the-trouble-with-geniuses-part-2","aria-label":'Permalink to "Chapter 4: The Trouble with Geniuses, Part 2"'},"​")],-1),d=l("",22);function u(p,m,f,g,w,b){const t=a;return n(),i("div",null,[c,s(t,{readTime:"8",words:"1.3k"}),d])}const T=o(h,[["render",u]]);export{L as __pageData,T as default}; +import{_ as a}from"./chunks/PageInfo.vue_vue_type_script_setup_true_lang.250b3e56.js";import{_ as o,o as n,c as i,H as s,k as e,a as r,Q as l}from"./chunks/framework.b7580407.js";import"./chunks/commonjsHelpers.725317a4.js";const L=JSON.parse('{"title":"Chapter 4: The Trouble with Geniuses, Part 2","description":"Chapter 4 summary of novel Outliers from Sparknotes","frontmatter":{"title":"Chapter 4: The Trouble with Geniuses, Part 2","description":"Chapter 4 summary of novel Outliers from Sparknotes"},"headers":[],"relativePath":"save/reading/outliers/4.md","filePath":"save/reading/outliers/4.md","lastUpdated":1699051935000}'),h={name:"save/reading/outliers/4.md"},c=e("h1",{id:"chapter-4-the-trouble-with-geniuses-part-2",tabindex:"-1"},[r("Chapter 4: The Trouble with Geniuses, Part 2 "),e("a",{class:"header-anchor",href:"#chapter-4-the-trouble-with-geniuses-part-2","aria-label":'Permalink to "Chapter 4: The Trouble with Geniuses, Part 2"'},"​")],-1),d=l("",22);function u(p,m,f,g,w,b){const t=a;return n(),i("div",null,[c,s(t,{readTime:"8",words:"1.3k"}),d])}const T=o(h,[["render",u]]);export{L as __pageData,T as default}; diff --git a/assets/style.41a6cfc6.css b/assets/style.41a6cfc6.css new file mode 100644 index 00000000..0761c5bb --- /dev/null +++ b/assets/style.41a6cfc6.css @@ -0,0 +1 @@ +@charset "UTF-8";@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-cyrillic.5f2c6c8c.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-cyrillic-ext.e75737ce.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-greek.d5a6d92a.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-greek-ext.ab0619bc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-latin.2ed14f66.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-latin-ext.0030eebd.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-vietnamese.14ce25a6.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-cyrillic.ea42a392.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-greek.8f4463c4.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-greek-ext.4fbe9427.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-latin.bd3b6f56.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-latin-ext.bd8920cc.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-vietnamese.6ce511fb.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Chinese Quotes;src:local("PingFang SC Regular"),local("PingFang SC"),local("SimHei"),local("Source Han Sans SC");unicode-range:U+2018,U+2019,U+201C,U+201D}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: rgba(60, 60, 67);--vp-c-text-2: rgba(60, 60, 67, .78);--vp-c-text-3: rgba(60, 60, 67, .56)}.dark{--vp-c-text-1: rgba(255, 255, 245, .86);--vp-c-text-2: rgba(235, 235, 245, .6);--vp-c-text-3: rgba(235, 235, 245, .38)}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Chinese Quotes", "Inter var", "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E")}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-green-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-green-1);--vp-code-line-diff-remove-color: var(--vp-c-red-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-red-1);--vp-code-line-warning-color: var(--vp-c-yellow-soft);--vp-code-line-error-color: var(--vp-c-red-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-brand-soft);--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-gray-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-brand-1);--vp-badge-tip-bg: var(--vp-c-brand-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);direction:ltr;font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{display:inline-block;margin:auto 2px -2px}mjx-container>svg{margin:auto}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-brand-1)}.custom-block.tip a:hover{color:var(--vp-c-brand-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code-light{display:none}html:not(.dark) .vp-code-dark{display:none}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s}.vp-doc blockquote>p{margin:0;font-size:16px;color:var(--vp-c-text-2);transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(.no-icon):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin-bottom:4px;text-align:center;letter-spacing:1px;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge[data-v-04be89dc]{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.vp-doc h1>.VPBadge[data-v-04be89dc]{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge[data-v-04be89dc]{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge[data-v-04be89dc]{vertical-align:middle}.vp-doc h4>.VPBadge[data-v-04be89dc],.vp-doc h5>.VPBadge[data-v-04be89dc],.vp-doc h6>.VPBadge[data-v-04be89dc]{vertical-align:middle;line-height:18px}.VPBadge.info[data-v-04be89dc]{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip[data-v-04be89dc]{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning[data-v-04be89dc]{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger[data-v-04be89dc]{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-5bbe8791]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-5bbe8791],.VPBackdrop.fade-leave-to[data-v-5bbe8791]{opacity:0}.VPBackdrop.fade-leave-active[data-v-5bbe8791]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-5bbe8791]{display:none}}.NotFound[data-v-8a8c82b4]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-8a8c82b4]{padding:96px 32px 168px}}.code[data-v-8a8c82b4]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-8a8c82b4]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-8a8c82b4]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-8a8c82b4]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-8a8c82b4]{padding-top:20px}.link[data-v-8a8c82b4]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-8a8c82b4]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-29e3fa2f]{position:relative;z-index:1}.nested[data-v-29e3fa2f]{padding-left:16px}.outline-link[data-v-29e3fa2f]{display:block;line-height:28px;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s;font-weight:400}.outline-link[data-v-29e3fa2f]:hover,.outline-link.active[data-v-29e3fa2f]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-29e3fa2f]{padding-left:13px}.VPDocAsideOutline[data-v-99fa007f]{display:none}.VPDocAsideOutline.has-outline[data-v-99fa007f]{display:block}.content[data-v-99fa007f]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-99fa007f]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-99fa007f]{letter-spacing:.4px;line-height:28px;font-size:13px;font-weight:600}.VPDocAside[data-v-f5b3965e]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-f5b3965e]{flex-grow:1}.VPDocAside[data-v-f5b3965e] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-f5b3965e] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-f5b3965e] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-ec8405ef]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-ec8405ef]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-bae355c8]{margin-top:64px}.edit-info[data-v-bae355c8]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-bae355c8]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-bae355c8]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-bae355c8]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-bae355c8]{margin-right:8px;width:14px;height:14px;fill:currentColor}.prev-next[data-v-bae355c8]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-bae355c8]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-bae355c8]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-bae355c8]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-bae355c8]{margin-left:auto;text-align:right}.desc[data-v-bae355c8]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-bae355c8]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDocOutlineDropdown[data-v-23cf0713]{margin-bottom:48px}.VPDocOutlineDropdown button[data-v-23cf0713]{display:block;font-size:14px;font-weight:500;line-height:24px;border:1px solid var(--vp-c-border);padding:4px 12px;color:var(--vp-c-text-2);background-color:var(--vp-c-default-soft);border-radius:8px;transition:color .5s}.VPDocOutlineDropdown button[data-v-23cf0713]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPDocOutlineDropdown button.open[data-v-23cf0713]{color:var(--vp-c-text-1)}.icon[data-v-23cf0713]{display:inline-block;vertical-align:middle;width:16px;height:16px;fill:currentColor}[data-v-23cf0713] .outline-link{font-size:14px;font-weight:400}.open>.icon[data-v-23cf0713]{transform:rotate(90deg)}.items[data-v-23cf0713]{margin-top:12px;border-left:1px solid var(--vp-c-divider)}.VPDoc[data-v-39e6c32d]{padding:32px 24px 96px;width:100%}.VPDoc .VPDocOutlineDropdown[data-v-39e6c32d]{display:none}@media (min-width: 960px) and (max-width: 1279px){.VPDoc .VPDocOutlineDropdown[data-v-39e6c32d]{display:block}}@media (min-width: 768px){.VPDoc[data-v-39e6c32d]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-39e6c32d]{padding:32px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-39e6c32d]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-39e6c32d]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-39e6c32d]{display:flex;justify-content:center}.VPDoc .aside[data-v-39e6c32d]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-39e6c32d]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-39e6c32d]{max-width:1104px}}.container[data-v-39e6c32d]{margin:0 auto;width:100%}.aside[data-v-39e6c32d]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-39e6c32d]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-39e6c32d]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 32px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-39e6c32d]::-webkit-scrollbar{display:none}.aside-curtain[data-v-39e6c32d]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-39e6c32d]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 32px));padding-bottom:32px}.content[data-v-39e6c32d]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-39e6c32d]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-39e6c32d]{order:1;margin:0;min-width:640px}}.content-container[data-v-39e6c32d]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-39e6c32d]{max-width:688px}.external-link-icon-enabled[data-v-39e6c32d] :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):after{content:"";color:currentColor}.VPButton[data-v-c5bc28bc]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-c5bc28bc]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-c5bc28bc]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-c5bc28bc]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-c5bc28bc]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-c5bc28bc]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-c5bc28bc]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-c5bc28bc]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-c5bc28bc]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-c5bc28bc]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-c5bc28bc]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-c5bc28bc]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-c5bc28bc]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-6ebf9bdf]{display:none}.dark .VPImage.light[data-v-6ebf9bdf]{display:none}.VPHero[data-v-95ba8d2c]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-95ba8d2c]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-95ba8d2c]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-95ba8d2c]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-95ba8d2c]{flex-direction:row}}.main[data-v-95ba8d2c]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-95ba8d2c]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-95ba8d2c]{text-align:left}}@media (min-width: 960px){.main[data-v-95ba8d2c]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-95ba8d2c]{max-width:592px}}.name[data-v-95ba8d2c],.text[data-v-95ba8d2c]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-95ba8d2c],.VPHero.has-image .text[data-v-95ba8d2c]{margin:0 auto}.name[data-v-95ba8d2c]{color:var(--vp-home-hero-name-color)}.clip[data-v-95ba8d2c]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-95ba8d2c],.text[data-v-95ba8d2c]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-95ba8d2c],.text[data-v-95ba8d2c]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-95ba8d2c],.VPHero.has-image .text[data-v-95ba8d2c]{margin:0}}.tagline[data-v-95ba8d2c]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-95ba8d2c]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-95ba8d2c]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-95ba8d2c]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-95ba8d2c]{margin:0}}.actions[data-v-95ba8d2c]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-95ba8d2c]{justify-content:center}@media (min-width: 640px){.actions[data-v-95ba8d2c]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-95ba8d2c]{justify-content:flex-start}}.action[data-v-95ba8d2c]{flex-shrink:0;padding:6px}.image[data-v-95ba8d2c]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-95ba8d2c]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-95ba8d2c]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-95ba8d2c]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-95ba8d2c]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-95ba8d2c]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-95ba8d2c]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-95ba8d2c]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-95ba8d2c]{width:320px;height:320px}}[data-v-95ba8d2c] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-95ba8d2c] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-95ba8d2c] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-5826beaa]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-5826beaa]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-5826beaa]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-5826beaa]>.VPImage{margin-bottom:20px}.icon[data-v-5826beaa]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-5826beaa]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-5826beaa]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-5826beaa]{padding-top:8px}.link-text-value[data-v-5826beaa]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-5826beaa]{display:inline-block;margin-left:6px;width:14px;height:14px;fill:currentColor}.VPFeatures[data-v-8aecaca0]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-8aecaca0]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-8aecaca0]{padding:0 64px}}.container[data-v-8aecaca0]{margin:0 auto;max-width:1152px}.items[data-v-8aecaca0]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-8aecaca0]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-8aecaca0],.item.grid-4[data-v-8aecaca0],.item.grid-6[data-v-8aecaca0]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-8aecaca0],.item.grid-4[data-v-8aecaca0]{width:50%}.item.grid-3[data-v-8aecaca0],.item.grid-6[data-v-8aecaca0]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-8aecaca0]{width:25%}}.VPHome[data-v-458cb9ca]{padding-bottom:96px}.VPHome[data-v-458cb9ca] .VPHomeSponsors{margin-top:112px;margin-bottom:-128px}@media (min-width: 768px){.VPHome[data-v-458cb9ca]{padding-bottom:128px}}.VPContent[data-v-f3ed2c70]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-f3ed2c70]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-f3ed2c70]{margin:0}@media (min-width: 960px){.VPContent[data-v-f3ed2c70]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-f3ed2c70]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-f3ed2c70]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-b69a1592]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-b69a1592]{display:none}@media (min-width: 768px){.VPFooter[data-v-b69a1592]{padding:32px}}.container[data-v-b69a1592]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-b69a1592],.copyright[data-v-b69a1592]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-44ae7a43]{padding:12px 20px 11px}.VPLocalNavOutlineDropdown button[data-v-44ae7a43]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-44ae7a43]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-44ae7a43]{color:var(--vp-c-text-1)}.icon[data-v-44ae7a43]{display:inline-block;vertical-align:middle;margin-left:2px;width:14px;height:14px;fill:currentColor}[data-v-44ae7a43] .outline-link{font-size:14px;padding:2px 0}.open>.icon[data-v-44ae7a43]{transform:rotate(90deg)}.items[data-v-44ae7a43]{position:absolute;top:64px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}.header[data-v-44ae7a43]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-44ae7a43]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-44ae7a43]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-44ae7a43]{transition:all .2s ease-out}.flyout-leave-active[data-v-44ae7a43]{transition:all .15s ease-in}.flyout-enter-from[data-v-44ae7a43],.flyout-leave-to[data-v-44ae7a43]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-a41c4a1c]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--vp-c-gutter);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-a41c4a1c]{position:fixed}.VPLocalNav.reached-top[data-v-a41c4a1c]{border-top-color:transparent}@media (min-width: 960px){.VPLocalNav[data-v-a41c4a1c]{display:none}}.menu[data-v-a41c4a1c]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-a41c4a1c]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-a41c4a1c]{padding:0 32px}}.menu-icon[data-v-a41c4a1c]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPOutlineDropdown[data-v-a41c4a1c]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-a41c4a1c]{padding:12px 32px 11px}}.VPSwitch[data-v-56eb52d1]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-56eb52d1]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-56eb52d1]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-56eb52d1]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-56eb52d1] svg{position:absolute;top:3px;left:3px;width:12px;height:12px;fill:var(--vp-c-text-2)}.dark .icon[data-v-56eb52d1] svg{fill:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-65b67168]{opacity:1}.moon[data-v-65b67168],.dark .sun[data-v-65b67168]{opacity:0}.dark .moon[data-v-65b67168]{opacity:1}.dark .VPSwitchAppearance[data-v-65b67168] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-dc7cad42]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-dc7cad42]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-ec5470f2]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-ec5470f2]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-ec5470f2]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-ec5470f2]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-b9d0e57b]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-b9d0e57b]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-b9d0e57b]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-b9d0e57b]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-17c3596a]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-17c3596a] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-17c3596a] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-17c3596a] .group:last-child{padding-bottom:0}.VPMenu[data-v-17c3596a] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-17c3596a] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-17c3596a] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-17c3596a] .action{padding-left:24px}.VPFlyout[data-v-62bba1f9]{position:relative}.VPFlyout[data-v-62bba1f9]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-62bba1f9]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-62bba1f9]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-62bba1f9]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-62bba1f9]{color:var(--vp-c-brand-2)}.VPFlyout:hover .menu[data-v-62bba1f9],.button[aria-expanded=true]+.menu[data-v-62bba1f9]{opacity:1;visibility:visible;transform:translateY(0)}.button[aria-expanded=false]+.menu[data-v-62bba1f9]{opacity:0;visibility:hidden;transform:translateY(0)}.button[data-v-62bba1f9]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-62bba1f9]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-62bba1f9]{margin-right:0;width:16px;height:16px;fill:currentColor}.text-icon[data-v-62bba1f9]{margin-left:4px;width:14px;height:14px;fill:currentColor}.icon[data-v-62bba1f9]{width:20px;height:20px;fill:currentColor;transition:fill .25s}.menu[data-v-62bba1f9]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-1b61e2c7]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-1b61e2c7]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-1b61e2c7]>svg{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-8a65be56]{display:flex;justify-content:center}.VPNavBarExtra[data-v-e5c8c6ca]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-e5c8c6ca]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-e5c8c6ca]{display:none}}.trans-title[data-v-e5c8c6ca]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-e5c8c6ca],.item.social-links[data-v-e5c8c6ca]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-e5c8c6ca]{min-width:176px}.appearance-action[data-v-e5c8c6ca]{margin-right:-2px}.social-links-list[data-v-e5c8c6ca]{margin:-4px -8px}.VPNavBarHamburger[data-v-f865e4ad]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-f865e4ad]{display:none}}.container[data-v-f865e4ad]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-f865e4ad]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-f865e4ad]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-f865e4ad]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-f865e4ad]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-f865e4ad]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-f865e4ad]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-f865e4ad],.VPNavBarHamburger.active:hover .middle[data-v-f865e4ad],.VPNavBarHamburger.active:hover .bottom[data-v-f865e4ad]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-f865e4ad],.middle[data-v-f865e4ad],.bottom[data-v-f865e4ad]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-f865e4ad]{top:0;left:0;transform:translate(0)}.middle[data-v-f865e4ad]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-f865e4ad]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-416f44b0]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-416f44b0],.VPNavBarMenuLink[data-v-416f44b0]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-183ec936]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-183ec936]{display:flex}}/*! @docsearch/css 3.5.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;position:relative;padding:0 0 2px;border:0;top:-1px;width:20px}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}[class*=DocSearch]{--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-background: transparent;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand-1);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:0!important}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"Ctrl";font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"⌘"}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand-1);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-default-soft)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-aaebde08]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-aaebde08]{display:flex;align-items:center}}.title[data-v-87c32abd]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-87c32abd]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-87c32abd]{border-bottom-color:var(--vp-c-divider)}}[data-v-87c32abd] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-fdfb8e5a]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-fdfb8e5a]{display:flex;align-items:center}}.title[data-v-fdfb8e5a]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-57f83237]{position:relative;border-bottom:1px solid transparent;padding:0 8px 0 24px;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap}@media (min-width: 768px){.VPNavBar[data-v-57f83237]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar[data-v-57f83237]{padding:0}.VPNavBar[data-v-57f83237]:not(.has-sidebar):not(.top){border-bottom-color:var(--vp-c-gutter);background-color:var(--vp-nav-bg-color)}}.container[data-v-57f83237]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-57f83237],.container>.content[data-v-57f83237]{pointer-events:none}.container[data-v-57f83237] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-57f83237]{max-width:100%}}.title[data-v-57f83237]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-57f83237]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-57f83237]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-57f83237]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-57f83237]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-57f83237]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-57f83237]{display:flex;justify-content:flex-end;align-items:center;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.top) .content-body[data-v-57f83237]{position:relative;background-color:var(--vp-nav-bg-color)}}@media (max-width: 767px){.content-body[data-v-57f83237]{column-gap:.5rem}}.menu+.translations[data-v-57f83237]:before,.menu+.appearance[data-v-57f83237]:before,.menu+.social-links[data-v-57f83237]:before,.translations+.appearance[data-v-57f83237]:before,.appearance+.social-links[data-v-57f83237]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-57f83237]:before,.translations+.appearance[data-v-57f83237]:before{margin-right:16px}.appearance+.social-links[data-v-57f83237]:before{margin-left:16px}.social-links[data-v-57f83237]{margin-right:-8px}@media (min-width: 960px){.VPNavBar.has-sidebar .curtain[data-v-57f83237]{position:absolute;right:0;bottom:-31px;width:calc(100% - var(--vp-sidebar-width));height:32px}.VPNavBar.has-sidebar .curtain[data-v-57f83237]:before{display:block;width:100%;height:32px;background:linear-gradient(var(--vp-c-bg),transparent 70%);content:""}}@media (min-width: 1440px){.VPNavBar.has-sidebar .curtain[data-v-57f83237]{width:calc(100% - ((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width)))}}.VPNavScreenAppearance[data-v-06a2ccf5]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-06a2ccf5]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-8ff91e12]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-8ff91e12]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-e7113d9e]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-e7113d9e]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-f4e6c868]{display:block}.title[data-v-f4e6c868]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-13f80375]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-13f80375]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-13f80375]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-13f80375]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-13f80375]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-13f80375]{transform:rotate(45deg)}.button[data-v-13f80375]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-13f80375]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-13f80375]{width:14px;height:14px;fill:var(--vp-c-text-2);transition:fill .5s,transform .25s}.group[data-v-13f80375]:first-child{padding-top:0}.group+.group[data-v-13f80375],.group+.item[data-v-13f80375]{padding-top:4px}.VPNavScreenTranslations[data-v-84369744]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-84369744]{height:auto}.title[data-v-84369744]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-84369744]{width:16px;height:16px;fill:currentColor}.icon.lang[data-v-84369744]{margin-right:8px}.icon.chevron[data-v-84369744]{margin-left:4px}.list[data-v-84369744]{padding:4px 0 0 24px}.link[data-v-84369744]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-796c739a]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 1px);right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .5s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-796c739a],.VPNavScreen.fade-leave-active[data-v-796c739a]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-796c739a],.VPNavScreen.fade-leave-active .container[data-v-796c739a]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-796c739a],.VPNavScreen.fade-leave-to[data-v-796c739a]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-796c739a],.VPNavScreen.fade-leave-to .container[data-v-796c739a]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-796c739a]{display:none}}.container[data-v-796c739a]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-796c739a],.menu+.appearance[data-v-796c739a],.translations+.appearance[data-v-796c739a]{margin-top:24px}.menu+.social-links[data-v-796c739a]{margin-top:16px}.appearance+.social-links[data-v-796c739a]{margin-top:16px}.VPNav[data-v-ff202323]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-ff202323]{position:fixed}}.VPSidebarItem.level-0[data-v-1b9f5c6f]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-1b9f5c6f]{padding-bottom:10px}.item[data-v-1b9f5c6f]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-1b9f5c6f]{cursor:pointer}.indicator[data-v-1b9f5c6f]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-1b9f5c6f],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-1b9f5c6f],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-1b9f5c6f],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-1b9f5c6f]{background-color:var(--vp-c-brand-1)}.link[data-v-1b9f5c6f]{display:flex;align-items:center;flex-grow:1}.text[data-v-1b9f5c6f]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-1b9f5c6f]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-1b9f5c6f],.VPSidebarItem.level-2 .text[data-v-1b9f5c6f],.VPSidebarItem.level-3 .text[data-v-1b9f5c6f],.VPSidebarItem.level-4 .text[data-v-1b9f5c6f],.VPSidebarItem.level-5 .text[data-v-1b9f5c6f]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-1b9f5c6f],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-1b9f5c6f],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-1b9f5c6f],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-1b9f5c6f],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-1b9f5c6f],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-1b9f5c6f]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-1b9f5c6f],.VPSidebarItem.level-1.has-active>.item>.text[data-v-1b9f5c6f],.VPSidebarItem.level-2.has-active>.item>.text[data-v-1b9f5c6f],.VPSidebarItem.level-3.has-active>.item>.text[data-v-1b9f5c6f],.VPSidebarItem.level-4.has-active>.item>.text[data-v-1b9f5c6f],.VPSidebarItem.level-5.has-active>.item>.text[data-v-1b9f5c6f],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-1b9f5c6f]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-1b9f5c6f],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-1b9f5c6f]{color:var(--vp-c-brand-1)}.caret[data-v-1b9f5c6f]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-1b9f5c6f]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-1b9f5c6f]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-1b9f5c6f]{width:18px;height:18px;fill:currentColor;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-1b9f5c6f]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-1b9f5c6f],.VPSidebarItem.level-2 .items[data-v-1b9f5c6f],.VPSidebarItem.level-3 .items[data-v-1b9f5c6f],.VPSidebarItem.level-4 .items[data-v-1b9f5c6f],.VPSidebarItem.level-5 .items[data-v-1b9f5c6f]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-1b9f5c6f]{display:none}.VPSidebar[data-v-7ab77f34]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-7ab77f34]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-7ab77f34]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-7ab77f34]{z-index:1;padding-top:var(--vp-nav-height);padding-bottom:128px;width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-7ab77f34]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-7ab77f34]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-7ab77f34]{outline:0}.group+.group[data-v-7ab77f34]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-7ab77f34]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSkipLink[data-v-315fcc9b]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-315fcc9b]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-315fcc9b]{top:14px;left:16px}}.Layout[data-v-f6284a77]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-507e6e02]{border-top:1px solid var(--vp-c-gutter);padding:88px 24px 96px;background-color:var(--vp-c-bg)}.container[data-v-507e6e02]{margin:0 auto;max-width:1152px}.love[data-v-507e6e02]{margin:0 auto;width:28px;height:28px;color:var(--vp-c-text-3)}.icon[data-v-507e6e02]{width:28px;height:28px;fill:currentColor}.message[data-v-507e6e02]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-507e6e02]{padding-top:32px}.action[data-v-507e6e02]{padding-top:40px;text-align:center}.VPTeamPage[data-v-af098aea]{padding-bottom:96px}@media (min-width: 768px){.VPTeamPage[data-v-af098aea]{padding-bottom:128px}}.VPTeamPageSection+.VPTeamPageSection[data-v-af098aea-s],.VPTeamMembers+.VPTeamPageSection[data-v-af098aea-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-af098aea-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-af098aea-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-af098aea-s],.VPTeamMembers+.VPTeamPageSection[data-v-af098aea-s]{margin-top:96px}}.VPTeamMembers[data-v-af098aea-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-af098aea-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-af098aea-s]{padding:0 64px}}.VPTeamPageTitle[data-v-464bef4f]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-464bef4f]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-464bef4f]{padding:80px 64px 48px}}.title[data-v-464bef4f]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-464bef4f]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-464bef4f]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-464bef4f]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-ea674020]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-ea674020]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-ea674020]{padding:0 64px}}.title[data-v-ea674020]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-ea674020]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-ea674020]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-ea674020]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-ea674020]{padding-top:40px}.VPTeamMembersItem[data-v-ac532fb0]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-ac532fb0]{padding:32px}.VPTeamMembersItem.small .data[data-v-ac532fb0]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-ac532fb0]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-ac532fb0]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-ac532fb0]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-ac532fb0]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-ac532fb0]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-ac532fb0]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-ac532fb0]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-ac532fb0]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-ac532fb0]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-ac532fb0]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-ac532fb0]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-ac532fb0]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-ac532fb0]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-ac532fb0]{text-align:center}.avatar[data-v-ac532fb0]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-ac532fb0]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-ac532fb0]{margin:0;font-weight:600}.affiliation[data-v-ac532fb0]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-ac532fb0]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-ac532fb0]:hover{color:var(--vp-c-brand-1)}.desc[data-v-ac532fb0]{margin:0 auto}.desc[data-v-ac532fb0] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-ac532fb0]{display:flex;justify-content:center;height:56px}.sp-link[data-v-ac532fb0]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-ac532fb0]:hover,.sp .sp-link.link[data-v-ac532fb0]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-ac532fb0]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPTeamMembers.small .container[data-v-f8911391]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-f8911391]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-f8911391]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-f8911391]{max-width:876px}.VPTeamMembers.medium .container[data-v-f8911391]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-f8911391]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-f8911391]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-f8911391]{max-width:760px}.container[data-v-f8911391]{display:grid;gap:24px;margin:0 auto;max-width:1152px}#nprogress{pointer-events:none}#nprogress .bar{background:var(--vp-c-brand);position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px var(--vp-c-brand),0 0 5px var(--vp-c-brand);opacity:1;-webkit-transform:rotate(3deg) translate(0px,-4px);-ms-transform:rotate(3deg) translate(0px,-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:var(--vp-c-brand);border-left-color:var(--vp-c-brand);border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .spinner,.nprogress-custom-parent #nprogress .bar{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:root{--vp-twoslash-c-annotation-fg: var(--vp-c-text-1);--vp-twoslash-c-brand: var(--vp-c-brand);--vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);--vp-twoslash-c-error-fg: var(--vp-c-text-1);--vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);--vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);--vp-twoslash-c-logger-fg: var(--vp-c-text-1);--vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);--vp-twoslash-c-logger-log-fg: var(--vp-c-gray);--vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);--vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);--vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);--vp-twoslash-c-lsp-border: var(--vp-c-divider);--vp-twoslash-c-lsp-fg: var(--vp-c-text-1);--vp-twoslash-c-lsp-underline: var(--vp-c-text-2) ;--vp-twoslash-lsp-shadow: var(--vp-shadow-2);--vp-twoslash-c-query-bg: var(--vp-c-mute-darker);--vp-twoslash-c-query-fg-2: var(--vp-c-text-2);--vp-twoslash-c-query-fg: var(--vp-c-text-1)}pre.shiki.twoslash,pre.shiki.twoslash code{background-color:unset!important;color:unset!important}@media (min-width: 640px){.vp-doc div[class*=language-],pre.shiki.twoslash{overflow:visible}}pre.shiki .language-id,.language-twoslash{display:none}pre .error,pre .error-behind{display:block;margin-bottom:4px;margin-left:-24px;margin-top:8px;padding:6px 6px 6px 24px;white-space:pre-wrap;width:100%}pre .error{position:absolute;background-color:var(--vp-twoslash-c-error-bg);display:flex;align-items:center;color:var(--vp-twoslash-c-error-fg)}pre .error .code{display:none}pre .error-behind{-webkit-user-select:none;user-select:none;visibility:transparent;color:transparent}pre .arrow{background-color:var(--vp-twoslash-c-query-bg);position:relative;top:-6px;margin-left:.1rem;border-left:1px solid var(--vp-twoslash-c-query-bg);border-top:1px solid var(--vp-twoslash-c-query-bg);transform:translateY(25%) rotate(45deg);height:8px;width:8px}pre .popover{color:var(--vp-twoslash-c-query-fg);margin-bottom:10px;background-color:var(--vp-twoslash-c-query-bg);display:inline-block;line-height:inherit;padding:0 .5rem .3rem;margin-top:8px;border-radius:3px;max-width:575px;white-space:pre-wrap}pre.twoslash:hover data-lsp{border-color:var(--vp-twoslash-c-lsp-underline)}pre.twoslash data-lsp:hover:before{content:attr(lsp);position:absolute;transform:translateY(1.15rem);color:var(--vp-twoslash-c-lsp-fg);background-color:var(--vp-twoslash-c-lsp-bg);border:1px solid var(--vp-twoslash-c-lsp-border);box-shadow:var(--vp-twoslash-lsp-shadow);text-align:left;padding:5px 8px;border-radius:3px;font-size:14px;white-space:pre-wrap;z-index:100}data-lsp{border-bottom:1px dotted transparent;transition-timing-function:ease;transition:border-color .3s}@media (prefers-reduced-motion: reduce){data-lsp{transition:none}}pre data-err{background:url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23c94824'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left;padding-bottom:3px}pre .code-container>a{position:absolute;right:9px;bottom:8px;border-radius:2px;background-image:url("data:image/svg+xml,%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3ETypeScript%3C/title%3E%3Cpath fill='%233078c6' d='M1.125 0C.502 0 0 .502 0 1.125v21.75C0 23.498.502 24 1.125 24h21.75c.623 0 1.125-.502 1.125-1.125V1.125C24 .502 23.498 0 22.875 0zm17.363 9.75c.612 0 1.154.037 1.627.111a6.38 6.38 0 0 1 1.306.34v2.458a3.95 3.95 0 0 0-.643-.361 5.093 5.093 0 0 0-.717-.26 5.453 5.453 0 0 0-1.426-.2c-.3 0-.573.028-.819.086a2.1 2.1 0 0 0-.623.242c-.17.104-.3.229-.393.374a.888.888 0 0 0-.14.49c0 .196.053.373.156.529.104.156.252.304.443.444s.423.276.696.41c.273.135.582.274.926.416.47.197.892.407 1.266.628.374.222.695.473.963.753.268.279.472.598.614.957.142.359.214.776.214 1.253 0 .657-.125 1.21-.373 1.656a3.033 3.033 0 0 1-1.012 1.085 4.38 4.38 0 0 1-1.487.596c-.566.12-1.163.18-1.79.18a9.916 9.916 0 0 1-1.84-.164 5.544 5.544 0 0 1-1.512-.493v-2.63a5.033 5.033 0 0 0 3.237 1.2c.333 0 .624-.03.872-.09.249-.06.456-.144.623-.25.166-.108.29-.234.373-.38a1.023 1.023 0 0 0-.074-1.089 2.12 2.12 0 0 0-.537-.5 5.597 5.597 0 0 0-.807-.444 27.72 27.72 0 0 0-1.007-.436c-.918-.383-1.602-.852-2.053-1.405-.45-.553-.676-1.222-.676-2.005 0-.614.123-1.141.369-1.582.246-.441.58-.804 1.004-1.089a4.494 4.494 0 0 1 1.47-.629 7.536 7.536 0 0 1 1.77-.201zm-15.113.188h9.563v2.166H9.506v9.646H6.789v-9.646H3.375z'/%3E%3C/svg%3E");background-color:#fff;width:20px;height:20px;color:transparent;text-decoration:none;opacity:0;transition-timing-function:ease;transition:opacity .3s}pre .code-container>a:hover{color:transparent}@media (prefers-reduced-motion: reduce){pre .code-container>a{transition:none}}pre .code-container:hover a{opacity:1}pre .inline-completions ul.dropdown{display:inline-block;position:absolute;width:240px;background-color:var(--vp-twoslash-c-query-bg);color:var(--vp-twoslash-c-query-fg-2);font-family:var(--code-font);margin:0;padding:0;border-left:4px solid var(--vp-twoslash-c-query-bg)}pre .inline-completions ul.dropdown:before{background-color:var(--vp-twoslash-c-query-fg);width:2px;position:absolute;top:-1.2rem;left:-3px;height:17px;content:" "}pre .inline-completions ul.dropdown li{overflow-x:hidden;padding-left:4px;margin-bottom:4px}pre .inline-completions ul.dropdown li.deprecated{text-decoration:line-through}pre .inline-completions ul.dropdown li span.result-found{color:var(--vp-twoslash-c-query-fg);font-weight:700}pre .inline-completions ul.dropdown li span.result{width:100px;color:var(--vp-twoslash-c-query-fg-2);display:inline-block}pre code[class*=language-]{all:unset!important}pre code[class*=language-] pre{padding:0!important}div[class*=language-] pre:not(.shiki){position:unset!important;white-space:inherit!important}pre .logger{display:flex;align-items:center;color:var(--vp-twoslash-c-logger-fg);padding:6px 6px 6px 8px;width:100%;white-space:pre-wrap}pre .logger svg{margin-right:9px}pre .logger.error-log{background-color:var(--vp-twoslash-c-logger-error-bg)}pre .logger.error-log svg path{fill:var(--vp-twoslash-c-logger-error-fg);stroke:var(--vp-twoslash-c-logger-error-fg)}pre .logger.warn-log{background-color:var(--vp-twoslash-c-logger-warn-bg)}pre .logger.warn-log svg path{fill:var(--vp-twoslash-c-logger-warn-fg);stroke:var(--vp-twoslash-c-logger-warn-fg)}pre .logger.log-log{background-color:var(--vp-twoslash-c-logger-log-bg)}pre .logger.log-log svg path,pre .logger.log-log svg line{fill:var(--vp-twoslash-c-logger-log-fg);stroke:var(--vp-twoslash-c-logger-log-fg)}pre .logger.log-log svg{margin-left:6px;margin-right:9px}.tag-container,.tag-container pre{position:unset!important}.tag-container .twoslash-annotation{position:absolute;right:-10px;width:200px;color:var(--vp-twoslash-c-brand);z-index:100}.tag-container .twoslash-annotation p{text-align:left;font-size:.8rem;line-height:.9rem}.tag-container .twoslash-annotation svg{float:left;margin-left:-44px}.tag-container .twoslash-annotation.left{right:auto;left:-200px}.tag-container .twoslash-annotation.left svg{float:right;margin-right:-5px}.tag-container .twoslash-annotation svg path{stroke:var(--vp-twoslash-c-annotation-fg)}pre.shiki:hover .dim{opacity:1}pre.shiki div.dim{opacity:.5}pre.shiki div.dim,pre.shiki div.highlight{margin:0;padding:0}pre.shiki div.highlight{opacity:1;background-color:var(--vp-c-mute-light)}pre.shiki div.line{min-height:1rem}pre.shiki span.line.highlighted{background-color:var(--vp-code-line-highlight-color)}pre code{-webkit-overflow-scrolling:touch}pre code a{text-decoration:none}pre .query{margin-bottom:10px;color:#137998;display:inline-block}*{scrollbar-color:var(--vp-c-divider-light) var(--vp-button-alt-bg);scrollbar-width:thin}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:var(--vp-c-mute)}::-webkit-scrollbar-thumb:hover{background:var(--vp-button-alt-hover-bg)}::-webkit-scrollbar-track{background:var(--vp-button-alt-bg)}::-webkit-scrollbar-corner{background:transparent}.katex{font-size:1.05em;direction:ltr}.katex-display{overflow:auto hidden;-webkit-overflow-scrolling:touch;padding-top:.2em;padding-bottom:.2em}.katex-display::-webkit-scrollbar{height:3px}.katex-display .katex{font-size:1.21em}.katex-error{color:red}.medium-zoom-image{z-index:21}.medium-zoom-image{align-items:center}.VPDoc .content-container img{border-radius:5px}.heart{animation:heart 5s ease infinite;color:red}@keyframes heart{0%{transform:scale(1)}5%{transform:scale(1.25)}20%{transform:scale(1)}30%{transform:scale(1)}35%{transform:scale(1.25)}50%{transform:scale(1)}55%{transform:scale(1.25)}70%{transform:scale(1)}}.coffee{color:#580d0d}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img.VPImage.image-src{width:300px}.vp-doc>div{width:100%}@media (min-width: 1440px){.VPDoc.has-aside .content-container.content-container{max-width:100%}}.vp-doc p a+a{margin-left:17px}@media (max-width: 1080px){:root{--vp-sidebar-width: 260px}.VPNav .DocSearch-Button-Placeholder{display:none}.VPNav .VPNavBarMenuLink,.VPNav .VPNavBarMenuGroup .button{padding-left:10px;padding-right:10px}}@media (max-width: 992px){.VPNav .VPNavBar{padding-left:24px;padding-right:24px}.VPNav .VPNavBarMenuLink,.VPNav .VPNavBarMenuGroup .button{padding-left:8px;padding-right:8px}}@media (max-width: 800px){.VPNav .VPNavBarSearch{padding-left:16px}.VPNav .VPNavBarMenuLink,.VPNav .VPNavBarMenuGroup .button{padding-left:6px;padding-right:6px}}.VPMenuGroup .title{white-space:nowrap}.DocSearch-Logo{display:none}.link-preview-widget{display:table;width:100%;border:2px solid rgba(55,53,47,.16);border-radius:5px}.link-preview-widget-title{font-size:16px;font-weight:700;display:-webkit-box;overflow:hidden;margin-bottom:8px;word-break:break-all;-webkit-box-orient:vertical;-webkit-line-clamp:2}.link-preview-widget-description{font-size:12px;font-style:normal;line-height:1.5;display:-webkit-box;overflow:hidden;max-height:3em;margin-bottom:4px;word-break:break-all;color:#37352fa6;-webkit-box-orient:vertical;-webkit-line-clamp:2}.link-preview-widget-url{font-size:12px;font-style:normal;line-height:1.5;display:block;margin-bottom:0;color:#37352fa6}.link-preview-widget>a{text-decoration:none!important;display:table-cell;flex-direction:column;padding:16px;cursor:pointer;vertical-align:middle;color:inherit;background-color:transparent;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;flex:1;transition:background-color .2s ease-in-out;border-radius:5px}.link-preview-widget>a:hover{background-color:var(--vp-custom-block-tip-bg)}.link-preview-widget-image{width:260px;min-width:220px;height:150px;padding:0;vertical-align:middle;border-left:1px rgba(55,53,47,.16) #f2f2f2;border-radius:5px;background-repeat:no-repeat;background-position:50%;background-size:cover;-webkit-box-flex:0;flex:0}html.dark .link-preview-widget{display:table;width:100%;border:2px solid rgba(200,202,208,.16);border-radius:5px}html.dark .link-preview-widget-title{font-size:16px;font-weight:700;display:-webkit-box;overflow:hidden;margin-bottom:8px;word-break:break-all;-webkit-box-orient:vertical;-webkit-line-clamp:2}html.dark .link-preview-widget-description{font-size:12px;font-style:normal;line-height:1.5;display:-webkit-box;overflow:hidden;max-height:3em;margin-bottom:4px;word-break:break-all;color:var(--vp-c-text-2);-webkit-box-orient:vertical;-webkit-line-clamp:2}html.dark .link-preview-widget-url{font-size:12px;font-style:normal;line-height:1.5;display:block;margin-bottom:0;color:var(--vp-c-text-2)}html.dark .link-preview-widget>a{text-decoration:none!important;display:table-cell;flex-direction:column;padding:16px;cursor:pointer;vertical-align:middle;color:inherit;background-color:transparent;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;flex:1;transition:background-color .2s ease-in-out}html.dark .link-preview-widget>a:hover{background-color:var(--vp-custom-block-tip-bg)}html.dark .link-preview-widget-image{width:260px;min-width:220px;height:150px;padding:0;vertical-align:middle;border-left:1px rgba(200,202,208,.16) #f2f2f2;border-radius:5px;background-repeat:no-repeat;background-position:50%;background-size:cover;-webkit-box-flex:0;flex:0}.vp-doc h2{border-top:0px;margin-top:10px}.VPMenuLink .link{line-height:28px!important}.VPSidebarGroup .link{padding:3px 0!important}.VPTeamPageTitle .title{line-height:32px;font-size:24px;opacity:.5}.VPTeamPageTitle .lead{font-size:14px;opacity:.4}.medium-zoom-overlay{z-index:20}.m-home-layout .image-src:hover{transform:translate(-50%,-50%) rotate(666turn);transition:transform 59s 1s cubic-bezier(.3,0,.8,1)}.m-home-layout .details small{opacity:.8}.m-home-layout .item:last-child .details{display:flex;justify-content:flex-end;align-items:end}:root{--vp-home-hero-name-color: transparent;--vp-home-hero-name-background: -webkit-linear-gradient(315deg, #42d392 25%, #647eff);--vp-home-hero-image-background-image: linear-gradient(-45deg, #42d392 50%, #47caff 50%);--vp-home-hero-image-filter: blur(40px)}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft)}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1)}:root{--vp-home-hero-name-color: transparent;--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe 30%, #41d1ff);--vp-home-hero-image-background-image: linear-gradient(-45deg, #bd34fe 50%, #47caff 50%);--vp-home-hero-image-filter: blur(40px)}@media (min-width: 640px){:root{--vp-home-hero-image-filter: blur(56px)}}@media (min-width: 960px){:root{--vp-home-hero-image-filter: blur(72px)}}:root{--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-brand-soft);--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft)}.DocSearch{--docsearch-primary-color: var(--vp-c-brand-1) !important}html:not(.dark) pre.shiki[class*=dark]{display:none}html:not(.dark) pre.shiki[class*=light]{display:block}html.dark pre.shiki[class*=dark]{display:block}html.dark pre.shiki[class*=light]{display:none}:root{--vp-twoslash-c-annotation-fg: var(--vp-c-text-1);--vp-twoslash-c-brand: var(--vp-c-brand);--vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);--vp-twoslash-c-error-fg: var(--vp-c-text-1);--vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);--vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);--vp-twoslash-c-logger-fg: var(--vp-c-text-1);--vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);--vp-twoslash-c-logger-log-fg: var(--vp-c-gray);--vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);--vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);--vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);--vp-twoslash-c-lsp-border: var(--vp-c-divider);--vp-twoslash-c-lsp-fg: var(--vp-c-text-1);--vp-twoslash-c-lsp-underline: var(--vp-c-text-2);--vp-twoslash-lsp-shadow: var(--vp-shadow-2);--vp-twoslash-c-query-bg: var(--vp-c-mute-dark);--vp-twoslash-c-query-fg-2: var(--vp-c-text-2);--vp-twoslash-c-query-fg: var(--vp-c-text-1)}.vp-code-group .tabs label{background-color:transparent;--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-active-text-color: var(--vp-c-text-1)}.home-content h2{margin-top:2rem;font-size:1.35rem;border-bottom:none;margin-bottom:0}img.resizable-img{width:unset;height:unset}*,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgba(0,0,0,0);--un-ring-shadow:0 0 rgba(0,0,0,0);--un-shadow-inset: ;--un-shadow:0 0 rgba(0,0,0,0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgba(0,0,0,0);--un-ring-shadow:0 0 rgba(0,0,0,0);--un-shadow-inset: ;--un-shadow:0 0 rgba(0,0,0,0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.static{position:static}.grid{display:grid}.m21{margin:5.25rem}.m9{margin:2.25rem}[ma=""]{margin:auto}.my{margin-top:1rem;margin-bottom:1rem}.mb{margin-bottom:1rem}.mb-\[12px\]{margin-bottom:12px}.me{margin-inline-end:1rem}.ms{margin-inline-start:1rem}.mt-\[24px\]{margin-top:24px}.inline{display:inline}.block,[block=""]{display:block}.inline-block{display:inline-block}.contents,[contents=""]{display:contents}.hidden{display:none}.h\$\.{height:var(--\.)}.h1{height:.25rem}.h2{height:.5rem}.h3{height:.75rem}.h4{height:1rem}.h5{height:1.25rem}.h6{height:1.5rem}.max-w-\[85\%\]{max-width:85%}.w-full{width:100%}.flex{display:flex}.flex-shrink{flex-shrink:1}.flex-grow{flex-grow:1}.flex-wrap{flex-wrap:wrap}.table{display:table}.transform{transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.items-center{align-items:center}.gap-\[12px\]{gap:12px}.gap-\[4px\]{gap:4px}.b,.b-1,.border,[b=""]{border-width:1px}.b\!{border-width:1px!important}.border-b-1{border-bottom-width:1px}.border-\[var\(--vp-c-divider\)\]{border-color:var(--vp-c-divider)}.border-b-solid{border-bottom-style:solid}[stroke-width~="2"]{stroke-width:2px}.px{padding-left:1rem;padding-right:1rem}.py{padding-top:1rem;padding-bottom:1rem}.pb-\[12px\]{padding-bottom:12px}.pl{padding-left:1rem}.pt{padding-top:1rem}.pie{padding-inline-end:1rem}.pie\!{padding-inline-end:1rem!important}.uppercase,[uppercase=""]{text-transform:uppercase}.lowercase,[lowercase=""]{text-transform:lowercase}.italic{font-style:italic}.tab{-moz-tab-size:4;-o-tab-size:4;tab-size:4}.outline{outline-style:solid}.blur{--un-blur:blur(8px);filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.filter{filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.ease{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-height:90px}.copyright[data-v-ddda9334]{border-color:var(--vp-custom-block-tip-border);border-style:solid;border-width:1px;background-color:var(--vp-custom-block-tip-bg);border-radius:6px;color:var(--vp-c-text-2);font-size:15px;margin-top:50px}.copyright .content[data-v-ddda9334]{padding:13px 16px}.copyright .content .item[data-v-ddda9334]{margin-bottom:5px;word-break:break-word;line-height:22px}.copyright .content .item .icon[data-v-ddda9334]{display:inline-block;height:16px;width:16px;margin-right:.375rem;vertical-align:-2.5px}a[data-v-ddda9334]{font-weight:400;color:var(--vp-c-text-2)}a[data-v-ddda9334]:hover{color:var(--vp-c-brand)}.copyrightText[data-v-ddda9334]{font-weight:700}/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{margin:0}main{display:block}h1{margin:.67em 0;font-size:2em}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-size:1em;font-family:monospace,monospace}a{background-color:transparent}abbr[title]{text-decoration:underline;text-decoration:underline dotted;border-bottom:none}b,strong{font-weight:bolder}code,kbd,samp{font-size:1em;font-family:monospace,monospace}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{margin:0;font-size:100%;font-family:inherit;line-height:1.15}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{display:table;box-sizing:border-box;max-width:100%;padding:0;color:inherit;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}.arco-icon{display:inline-block;width:1em;height:1em;color:inherit;font-style:normal;vertical-align:-2px;outline:none;stroke:currentColor}.arco-icon-loading,.arco-icon-spin{animation:arco-loading-circle 1s infinite cubic-bezier(0,0,1,1)}@keyframes arco-loading-circle{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.arco-icon-hover{position:relative;display:inline-block;cursor:pointer;line-height:12px}.arco-icon-hover .arco-icon{position:relative}.arco-icon-hover:before{position:absolute;display:block;box-sizing:border-box;background-color:transparent;border-radius:var(--border-radius-circle);transition:background-color .1s cubic-bezier(0,0,1,1);content:""}.arco-icon-hover:hover:before{background-color:var(--color-fill-2)}.arco-icon-hover.arco-icon-hover-disabled:before{opacity:0}.arco-icon-hover:before{top:50%;left:50%;width:20px;height:20px;transform:translate(-50%,-50%)}.arco-icon-hover-size-mini{line-height:12px}.arco-icon-hover-size-mini:before{top:50%;left:50%;width:20px;height:20px;transform:translate(-50%,-50%)}.arco-icon-hover-size-small{line-height:12px}.arco-icon-hover-size-small:before{top:50%;left:50%;width:20px;height:20px;transform:translate(-50%,-50%)}.arco-icon-hover-size-large{line-height:12px}.arco-icon-hover-size-large:before{top:50%;left:50%;width:24px;height:24px;transform:translate(-50%,-50%)}.arco-icon-hover-size-huge{line-height:12px}.arco-icon-hover-size-huge:before{top:50%;left:50%;width:24px;height:24px;transform:translate(-50%,-50%)}.fade-in-standard-enter-from,.fade-in-standard-appear-from{opacity:0}.fade-in-standard-enter-to,.fade-in-standard-appear-to{opacity:1}.fade-in-standard-enter-active,.fade-in-standard-appear-active{transition:opacity .3s cubic-bezier(.34,.69,.1,1)}.fade-in-standard-leave-from{opacity:1}.fade-in-standard-leave-to{opacity:0}.fade-in-standard-leave-active{transition:opacity .3s cubic-bezier(.34,.69,.1,1)}.fade-in-enter-from,.fade-in-appear-from{opacity:0}.fade-in-enter-to,.fade-in-appear-to{opacity:1}.fade-in-enter-active,.fade-in-appear-active{transition:opacity .1s cubic-bezier(0,0,1,1)}.fade-in-leave-from{opacity:1}.fade-in-leave-to{opacity:0}.fade-in-leave-active{transition:opacity .1s cubic-bezier(0,0,1,1)}.zoom-in-enter-from,.zoom-in-appear-from{transform:scale(.5);opacity:0}.zoom-in-enter-to,.zoom-in-appear-to{transform:scale(1);opacity:1}.zoom-in-enter-active,.zoom-in-appear-active{transition:opacity .3s cubic-bezier(.34,.69,.1,1),transform .3s cubic-bezier(.34,.69,.1,1)}.zoom-in-leave-from{transform:scale(1);opacity:1}.zoom-in-leave-to{transform:scale(.5);opacity:0}.zoom-in-leave-active{transition:opacity .3s cubic-bezier(.34,.69,.1,1),transform .3s cubic-bezier(.34,.69,.1,1)}.zoom-in-fade-out-enter-from,.zoom-in-fade-out-appear-from{transform:scale(.5);opacity:0}.zoom-in-fade-out-enter-to,.zoom-in-fade-out-appear-to{transform:scale(1);opacity:1}.zoom-in-fade-out-enter-active,.zoom-in-fade-out-appear-active{transition:opacity .3s cubic-bezier(.3,1.3,.3,1),transform .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-fade-out-leave-from{transform:scale(1);opacity:1}.zoom-in-fade-out-leave-to{transform:scale(.5);opacity:0}.zoom-in-fade-out-leave-active{transition:opacity .3s cubic-bezier(.3,1.3,.3,1),transform .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-big-enter-from,.zoom-in-big-appear-from{transform:scale(.5);opacity:0}.zoom-in-big-enter-to,.zoom-in-big-appear-to{transform:scale(1);opacity:1}.zoom-in-big-enter-active,.zoom-in-big-appear-active{transition:opacity .2s cubic-bezier(0,0,1,1),transform .2s cubic-bezier(0,0,1,1)}.zoom-in-big-leave-from{transform:scale(1);opacity:1}.zoom-in-big-leave-to{transform:scale(.2);opacity:0}.zoom-in-big-leave-active{transition:opacity .2s cubic-bezier(0,0,1,1),transform .2s cubic-bezier(0,0,1,1)}.zoom-in-left-enter-from,.zoom-in-left-appear-from{transform:scale(.1);opacity:.1}.zoom-in-left-enter-to,.zoom-in-left-appear-to{transform:scale(1);opacity:1}.zoom-in-left-enter-active,.zoom-in-left-appear-active{transform-origin:0 50%;transition:opacity .3s cubic-bezier(0,0,1,1),transform .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-left-leave-from{transform:scale(1);opacity:1}.zoom-in-left-leave-to{transform:scale(.1);opacity:.1}.zoom-in-left-leave-active{transform-origin:0 50%;transition:opacity .3s cubic-bezier(0,0,1,1),transform .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-top-enter-from,.zoom-in-top-appear-from{transform:scaleY(.8) translateZ(0);opacity:0}.zoom-in-top-enter-to,.zoom-in-top-appear-to{transform:scaleY(1) translateZ(0);opacity:1}.zoom-in-top-enter-active,.zoom-in-top-appear-active{transform-origin:0 0;transition:transform .3s cubic-bezier(.3,1.3,.3,1),opacity .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-top-leave-from{transform:scaleY(1) translateZ(0);opacity:1}.zoom-in-top-leave-to{transform:scaleY(.8) translateZ(0);opacity:0}.zoom-in-top-leave-active{transform-origin:0 0;transition:transform .3s cubic-bezier(.3,1.3,.3,1),opacity .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-bottom-enter-from,.zoom-in-bottom-appear-from{transform:scaleY(.8) translateZ(0);opacity:0}.zoom-in-bottom-enter-to,.zoom-in-bottom-appear-to{transform:scaleY(1) translateZ(0);opacity:1}.zoom-in-bottom-enter-active,.zoom-in-bottom-appear-active{transform-origin:100% 100%;transition:transform .3s cubic-bezier(.3,1.3,.3,1),opacity .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-bottom-leave-from{transform:scaleY(1) translateZ(0);opacity:1}.zoom-in-bottom-leave-to{transform:scaleY(.8) translateZ(0);opacity:0}.zoom-in-bottom-leave-active{transform-origin:100% 100%;transition:transform .3s cubic-bezier(.3,1.3,.3,1),opacity .3s cubic-bezier(.3,1.3,.3,1)}.slide-dynamic-origin-enter-from,.slide-dynamic-origin-appear-from{transform:scaleY(.9);transform-origin:0 0;opacity:0}.slide-dynamic-origin-enter-to,.slide-dynamic-origin-appear-to{transform:scaleY(1);transform-origin:0 0;opacity:1}.slide-dynamic-origin-enter-active,.slide-dynamic-origin-appear-active{transition:transform .2s cubic-bezier(.34,.69,.1,1),opacity .2s cubic-bezier(.34,.69,.1,1)}.slide-dynamic-origin-leave-from{transform:scaleY(1);transform-origin:0 0;opacity:1}.slide-dynamic-origin-leave-to{transform:scaleY(.9);transform-origin:0 0;opacity:0}.slide-dynamic-origin-leave-active{transition:transform .2s cubic-bezier(.34,.69,.1,1),opacity .2s cubic-bezier(.34,.69,.1,1)}.slide-left-enter-from,.slide-left-appear-from{transform:translate(-100%)}.slide-left-enter-to,.slide-left-appear-to{transform:translate(0)}.slide-left-enter-active,.slide-left-appear-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-left-leave-from{transform:translate(0)}.slide-left-leave-to{transform:translate(-100%)}.slide-left-leave-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-right-enter-from,.slide-right-appear-from{transform:translate(100%)}.slide-right-enter-to,.slide-right-appear-to{transform:translate(0)}.slide-right-enter-active,.slide-right-appear-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-right-leave-from{transform:translate(0)}.slide-right-leave-to{transform:translate(100%)}.slide-right-leave-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-top-enter-from,.slide-top-appear-from{transform:translateY(-100%)}.slide-top-enter-to,.slide-top-appear-to{transform:translateY(0)}.slide-top-enter-active,.slide-top-appear-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-top-leave-from{transform:translateY(0)}.slide-top-leave-to{transform:translateY(-100%)}.slide-top-leave-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-bottom-enter-from,.slide-bottom-appear-from{transform:translateY(100%)}.slide-bottom-enter-to,.slide-bottom-appear-to{transform:translateY(0)}.slide-bottom-enter-active,.slide-bottom-appear-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-bottom-leave-from{transform:translateY(0)}.slide-bottom-leave-to{transform:translateY(100%)}.slide-bottom-leave-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}body{--red-1: 255,236,232;--red-2: 253,205,197;--red-3: 251,172,163;--red-4: 249,137,129;--red-5: 247,101,96;--red-6: 245,63,63;--red-7: 203,39,45;--red-8: 161,21,30;--red-9: 119,8,19;--red-10: 77,0,10;--orangered-1: 255,243,232;--orangered-2: 253,221,195;--orangered-3: 252,197,159;--orangered-4: 250,172,123;--orangered-5: 249,144,87;--orangered-6: 247,114,52;--orangered-7: 204,81,32;--orangered-8: 162,53,17;--orangered-9: 119,31,6;--orangered-10: 77,14,0;--orange-1: 255,247,232;--orange-2: 255,228,186;--orange-3: 255,207,139;--orange-4: 255,182,93;--orange-5: 255,154,46;--orange-6: 255,125,0;--orange-7: 210,95,0;--orange-8: 166,69,0;--orange-9: 121,46,0;--orange-10: 77,27,0;--gold-1: 255,252,232;--gold-2: 253,244,191;--gold-3: 252,233,150;--gold-4: 250,220,109;--gold-5: 249,204,69;--gold-6: 247,186,30;--gold-7: 204,146,19;--gold-8: 162,109,10;--gold-9: 119,75,4;--gold-10: 77,45,0;--yellow-1: 254,255,232;--yellow-2: 254,254,190;--yellow-3: 253,250,148;--yellow-4: 252,242,107;--yellow-5: 251,232,66;--yellow-6: 250,220,25;--yellow-7: 207,175,15;--yellow-8: 163,132,8;--yellow-9: 120,93,3;--yellow-10: 77,56,0;--lime-1: 252,255,232;--lime-2: 237,248,187;--lime-3: 220,241,144;--lime-4: 201,233,104;--lime-5: 181,226,65;--lime-6: 159,219,29;--lime-7: 126,183,18;--lime-8: 95,148,10;--lime-9: 67,112,4;--lime-10: 42,77,0;--green-1: 232,255,234;--green-2: 175,240,181;--green-3: 123,225,136;--green-4: 76,210,99;--green-5: 35,195,67;--green-6: 0,180,42;--green-7: 0,154,41;--green-8: 0,128,38;--green-9: 0,102,34;--green-10: 0,77,28;--cyan-1: 232,255,251;--cyan-2: 183,244,236;--cyan-3: 137,233,224;--cyan-4: 94,223,214;--cyan-5: 55,212,207;--cyan-6: 20,201,201;--cyan-7: 13,165,170;--cyan-8: 7,130,139;--cyan-9: 3,97,108;--cyan-10: 0,66,77;--blue-1: 232,247,255;--blue-2: 195,231,254;--blue-3: 159,212,253;--blue-4: 123,192,252;--blue-5: 87,169,251;--blue-6: 52,145,250;--blue-7: 32,108,207;--blue-8: 17,75,163;--blue-9: 6,48,120;--blue-10: 0,26,77;--arcoblue-1: 232,243,255;--arcoblue-2: 190,218,255;--arcoblue-3: 148,191,255;--arcoblue-4: 106,161,255;--arcoblue-5: 64,128,255;--arcoblue-6: 22,93,255;--arcoblue-7: 14,66,210;--arcoblue-8: 7,44,166;--arcoblue-9: 3,26,121;--arcoblue-10: 0,13,77;--purple-1: 245,232,255;--purple-2: 221,190,246;--purple-3: 195,150,237;--purple-4: 168,113,227;--purple-5: 141,78,218;--purple-6: 114,46,209;--purple-7: 85,29,176;--purple-8: 60,16,143;--purple-9: 39,6,110;--purple-10: 22,0,77;--pinkpurple-1: 255,232,251;--pinkpurple-2: 247,186,239;--pinkpurple-3: 240,142,230;--pinkpurple-4: 232,101,223;--pinkpurple-5: 225,62,219;--pinkpurple-6: 217,26,217;--pinkpurple-7: 176,16,182;--pinkpurple-8: 138,9,147;--pinkpurple-9: 101,3,112;--pinkpurple-10: 66,0,77;--magenta-1: 255,232,241;--magenta-2: 253,194,219;--magenta-3: 251,157,199;--magenta-4: 249,121,183;--magenta-5: 247,84,168;--magenta-6: 245,49,157;--magenta-7: 203,30,131;--magenta-8: 161,16,105;--magenta-9: 119,6,79;--magenta-10: 77,0,52;--gray-1: 247,248,250;--gray-2: 242,243,245;--gray-3: 229,230,235;--gray-4: 201,205,212;--gray-5: 169,174,184;--gray-6: 134,144,156;--gray-7: 107,119,133;--gray-8: 78,89,105;--gray-9: 39,46,59;--gray-10: 29,33,41;--success-1: var(--green-1);--success-2: var(--green-2);--success-3: var(--green-3);--success-4: var(--green-4);--success-5: var(--green-5);--success-6: var(--green-6);--success-7: var(--green-7);--success-8: var(--green-8);--success-9: var(--green-9);--success-10: var(--green-10);--primary-1: var(--arcoblue-1);--primary-2: var(--arcoblue-2);--primary-3: var(--arcoblue-3);--primary-4: var(--arcoblue-4);--primary-5: var(--arcoblue-5);--primary-6: var(--arcoblue-6);--primary-7: var(--arcoblue-7);--primary-8: var(--arcoblue-8);--primary-9: var(--arcoblue-9);--primary-10: var(--arcoblue-10);--danger-1: var(--red-1);--danger-2: var(--red-2);--danger-3: var(--red-3);--danger-4: var(--red-4);--danger-5: var(--red-5);--danger-6: var(--red-6);--danger-7: var(--red-7);--danger-8: var(--red-8);--danger-9: var(--red-9);--danger-10: var(--red-10);--warning-1: var(--orange-1);--warning-2: var(--orange-2);--warning-3: var(--orange-3);--warning-4: var(--orange-4);--warning-5: var(--orange-5);--warning-6: var(--orange-6);--warning-7: var(--orange-7);--warning-8: var(--orange-8);--warning-9: var(--orange-9);--warning-10: var(--orange-10);--link-1: var(--arcoblue-1);--link-2: var(--arcoblue-2);--link-3: var(--arcoblue-3);--link-4: var(--arcoblue-4);--link-5: var(--arcoblue-5);--link-6: var(--arcoblue-6);--link-7: var(--arcoblue-7);--link-8: var(--arcoblue-8);--link-9: var(--arcoblue-9);--link-10: var(--arcoblue-10)}body[arco-theme=dark]{--red-1: 77,0,10;--red-2: 119,6,17;--red-3: 161,22,31;--red-4: 203,46,52;--red-5: 245,78,78;--red-6: 247,105,101;--red-7: 249,141,134;--red-8: 251,176,167;--red-9: 253,209,202;--red-10: 255,240,236;--orangered-1: 77,14,0;--orangered-2: 119,30,5;--orangered-3: 162,55,20;--orangered-4: 204,87,41;--orangered-5: 247,126,69;--orangered-6: 249,146,90;--orangered-7: 250,173,125;--orangered-8: 252,198,161;--orangered-9: 253,222,197;--orangered-10: 255,244,235;--orange-1: 77,27,0;--orange-2: 121,48,4;--orange-3: 166,75,10;--orange-4: 210,105,19;--orange-5: 255,141,31;--orange-6: 255,150,38;--orange-7: 255,179,87;--orange-8: 255,205,135;--orange-9: 255,227,184;--orange-10: 255,247,232;--gold-1: 77,45,0;--gold-2: 119,75,4;--gold-3: 162,111,15;--gold-4: 204,150,31;--gold-5: 247,192,52;--gold-6: 249,204,68;--gold-7: 250,220,108;--gold-8: 252,233,149;--gold-9: 253,244,190;--gold-10: 255,252,232;--yellow-1: 77,56,0;--yellow-2: 120,94,7;--yellow-3: 163,134,20;--yellow-4: 207,179,37;--yellow-5: 250,225,60;--yellow-6: 251,233,75;--yellow-7: 252,243,116;--yellow-8: 253,250,157;--yellow-9: 254,254,198;--yellow-10: 254,255,240;--lime-1: 42,77,0;--lime-2: 68,112,6;--lime-3: 98,148,18;--lime-4: 132,183,35;--lime-5: 168,219,57;--lime-6: 184,226,75;--lime-7: 203,233,112;--lime-8: 222,241,152;--lime-9: 238,248,194;--lime-10: 253,255,238;--green-1: 0,77,28;--green-2: 4,102,37;--green-3: 10,128,45;--green-4: 18,154,55;--green-5: 29,180,64;--green-6: 39,195,70;--green-7: 80,210,102;--green-8: 126,225,139;--green-9: 178,240,183;--green-10: 235,255,236;--cyan-1: 0,66,77;--cyan-2: 6,97,108;--cyan-3: 17,131,139;--cyan-4: 31,166,170;--cyan-5: 48,201,201;--cyan-6: 63,212,207;--cyan-7: 102,223,215;--cyan-8: 144,233,225;--cyan-9: 190,244,237;--cyan-10: 240,255,252;--blue-1: 0,26,77;--blue-2: 5,47,120;--blue-3: 19,76,163;--blue-4: 41,113,207;--blue-5: 70,154,250;--blue-6: 90,170,251;--blue-7: 125,193,252;--blue-8: 161,213,253;--blue-9: 198,232,254;--blue-10: 234,248,255;--arcoblue-1: 0,13,77;--arcoblue-2: 4,27,121;--arcoblue-3: 14,50,166;--arcoblue-4: 29,77,210;--arcoblue-5: 48,111,255;--arcoblue-6: 60,126,255;--arcoblue-7: 104,159,255;--arcoblue-8: 147,190,255;--arcoblue-9: 190,218,255;--arcoblue-10: 234,244,255;--purple-1: 22,0,77;--purple-2: 39,6,110;--purple-3: 62,19,143;--purple-4: 90,37,176;--purple-5: 123,61,209;--purple-6: 142,81,218;--purple-7: 169,116,227;--purple-8: 197,154,237;--purple-9: 223,194,246;--purple-10: 247,237,255;--pinkpurple-1: 66,0,77;--pinkpurple-2: 101,3,112;--pinkpurple-3: 138,13,147;--pinkpurple-4: 176,27,182;--pinkpurple-5: 217,46,217;--pinkpurple-6: 225,61,219;--pinkpurple-7: 232,102,223;--pinkpurple-8: 240,146,230;--pinkpurple-9: 247,193,240;--pinkpurple-10: 255,242,253;--magenta-1: 77,0,52;--magenta-2: 119,8,80;--magenta-3: 161,23,108;--magenta-4: 203,43,136;--magenta-5: 245,69,166;--magenta-6: 247,86,169;--magenta-7: 249,122,184;--magenta-8: 251,158,200;--magenta-9: 253,195,219;--magenta-10: 255,232,241;--gray-1: 23,23,26;--gray-2: 46,46,48;--gray-3: 72,72,73;--gray-4: 95,95,96;--gray-5: 120,120,122;--gray-6: 146,146,147;--gray-7: 171,171,172;--gray-8: 197,197,197;--gray-9: 223,223,223;--gray-10: 246,246,246;--primary-1: var(--arcoblue-1);--primary-2: var(--arcoblue-2);--primary-3: var(--arcoblue-3);--primary-4: var(--arcoblue-4);--primary-5: var(--arcoblue-5);--primary-6: var(--arcoblue-6);--primary-7: var(--arcoblue-7);--primary-8: var(--arcoblue-8);--primary-9: var(--arcoblue-9);--primary-10: var(--arcoblue-10);--success-1: var(--green-1);--success-2: var(--green-2);--success-3: var(--green-3);--success-4: var(--green-4);--success-5: var(--green-5);--success-6: var(--green-6);--success-7: var(--green-7);--success-8: var(--green-8);--success-9: var(--green-9);--success-10: var(--green-10);--danger-1: var(--red-1);--danger-2: var(--red-2);--danger-3: var(--red-3);--danger-4: var(--red-4);--danger-5: var(--red-5);--danger-6: var(--red-6);--danger-7: var(--red-7);--danger-8: var(--red-8);--danger-9: var(--red-9);--danger-10: var(--red-10);--warning-1: var(--orange-1);--warning-2: var(--orange-2);--warning-3: var(--orange-3);--warning-4: var(--orange-4);--warning-5: var(--orange-5);--warning-6: var(--orange-6);--warning-7: var(--orange-7);--warning-8: var(--orange-8);--warning-9: var(--orange-9);--warning-10: var(--orange-10);--link-1: var(--arcoblue-1);--link-2: var(--arcoblue-2);--link-3: var(--arcoblue-3);--link-4: var(--arcoblue-4);--link-5: var(--arcoblue-5);--link-6: var(--arcoblue-6);--link-7: var(--arcoblue-7);--link-8: var(--arcoblue-8);--link-9: var(--arcoblue-9);--link-10: var(--arcoblue-10)}body{--color-white: #ffffff;--color-black: #000000;--color-border: rgb(var(--gray-3));--color-bg-popup: var(--color-bg-5);--color-bg-1: #fff;--color-bg-2: #fff;--color-bg-3: #fff;--color-bg-4: #fff;--color-bg-5: #fff;--color-bg-white: #fff;--color-neutral-1: rgb(var(--gray-1));--color-neutral-2: rgb(var(--gray-2));--color-neutral-3: rgb(var(--gray-3));--color-neutral-4: rgb(var(--gray-4));--color-neutral-5: rgb(var(--gray-5));--color-neutral-6: rgb(var(--gray-6));--color-neutral-7: rgb(var(--gray-7));--color-neutral-8: rgb(var(--gray-8));--color-neutral-9: rgb(var(--gray-9));--color-neutral-10: rgb(var(--gray-10));--color-text-1: var(--color-neutral-10);--color-text-2: var(--color-neutral-8);--color-text-3: var(--color-neutral-6);--color-text-4: var(--color-neutral-4);--color-border-1: var(--color-neutral-2);--color-border-2: var(--color-neutral-3);--color-border-3: var(--color-neutral-4);--color-border-4: var(--color-neutral-6);--color-fill-1: var(--color-neutral-1);--color-fill-2: var(--color-neutral-2);--color-fill-3: var(--color-neutral-3);--color-fill-4: var(--color-neutral-4);--color-primary-light-1: rgb(var(--primary-1));--color-primary-light-2: rgb(var(--primary-2));--color-primary-light-3: rgb(var(--primary-3));--color-primary-light-4: rgb(var(--primary-4));--color-link-light-1: rgb(var(--link-1));--color-link-light-2: rgb(var(--link-2));--color-link-light-3: rgb(var(--link-3));--color-link-light-4: rgb(var(--link-4));--color-secondary: var(--color-neutral-2);--color-secondary-hover: var(--color-neutral-3);--color-secondary-active: var(--color-neutral-4);--color-secondary-disabled: var(--color-neutral-1);--color-danger-light-1: rgb(var(--danger-1));--color-danger-light-2: rgb(var(--danger-2));--color-danger-light-3: rgb(var(--danger-3));--color-danger-light-4: rgb(var(--danger-4));--color-success-light-1: rgb(var(--success-1));--color-success-light-2: rgb(var(--success-2));--color-success-light-3: rgb(var(--success-3));--color-success-light-4: rgb(var(--success-4));--color-warning-light-1: rgb(var(--warning-1));--color-warning-light-2: rgb(var(--warning-2));--color-warning-light-3: rgb(var(--warning-3));--color-warning-light-4: rgb(var(--warning-4));--border-radius-none: 0;--border-radius-small: 2px;--border-radius-medium: 4px;--border-radius-large: 8px;--border-radius-circle: 50%;--color-tooltip-bg: rgb(var(--gray-10));--color-spin-layer-bg: rgba(255, 255, 255, .6);--color-menu-dark-bg: #232324;--color-menu-light-bg: #ffffff;--color-menu-dark-hover: rgba(255, 255, 255, .04);--color-mask-bg: rgba(29, 33, 41, .6)}body[arco-theme=dark]{--color-white: rgba(255, 255, 255, .9);--color-black: #000000;--color-border: #333335;--color-bg-1: #17171a;--color-bg-2: #232324;--color-bg-3: #2a2a2b;--color-bg-4: #313132;--color-bg-5: #373739;--color-bg-white: #f6f6f6;--color-text-1: rgba(255, 255, 255, .9);--color-text-2: rgba(255, 255, 255, .7);--color-text-3: rgba(255, 255, 255, .5);--color-text-4: rgba(255, 255, 255, .3);--color-fill-1: rgba(255, 255, 255, .04);--color-fill-2: rgba(255, 255, 255, .08);--color-fill-3: rgba(255, 255, 255, .12);--color-fill-4: rgba(255, 255, 255, .16);--color-primary-light-1: rgba(var(--primary-6), .2);--color-primary-light-2: rgba(var(--primary-6), .35);--color-primary-light-3: rgba(var(--primary-6), .5);--color-primary-light-4: rgba(var(--primary-6), .65);--color-secondary: rgba(var(--gray-9), .08);--color-secondary-hover: rgba(var(--gray-8), .16);--color-secondary-active: rgba(var(--gray-7), .24);--color-secondary-disabled: rgba(var(--gray-9), .08);--color-danger-light-1: rgba(var(--danger-6), .2);--color-danger-light-2: rgba(var(--danger-6), .35);--color-danger-light-3: rgba(var(--danger-6), .5);--color-danger-light-4: rgba(var(--danger-6), .65);--color-success-light-1: rgb(var(--success-6), .2);--color-success-light-2: rgb(var(--success-6), .35);--color-success-light-3: rgb(var(--success-6), .5);--color-success-light-4: rgb(var(--success-6), .65);--color-warning-light-1: rgb(var(--warning-6), .2);--color-warning-light-2: rgb(var(--warning-6), .35);--color-warning-light-3: rgb(var(--warning-6), .5);--color-warning-light-4: rgb(var(--warning-6), .65);--color-link-light-1: rgb(var(--link-6), .2);--color-link-light-2: rgb(var(--link-6), .35);--color-link-light-3: rgb(var(--link-6), .5);--color-link-light-4: rgb(var(--link-6), .65);--color-tooltip-bg: #373739;--color-spin-layer-bg: rgba(51, 51, 51, .6);--color-menu-dark-bg: #232324;--color-menu-light-bg: #232324;--color-menu-dark-hover: var(--color-fill-2);--color-mask-bg: rgba(23, 23, 26, .6)}body{font-size:14px;font-family:Inter,-apple-system,BlinkMacSystemFont,PingFang SC,Hiragino Sans GB,noto sans,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif}.arco-message-list{position:fixed;z-index:1003;display:flex;flex-direction:column;align-items:center;box-sizing:border-box;width:100%;margin:0;padding:0 10px;text-align:center;pointer-events:none}.arco-message-list-top{top:40px}.arco-message-list-bottom{bottom:40px}.arco-message{position:relative;display:inline-flex;align-items:center;margin-bottom:16px;padding:10px 16px;overflow:hidden;line-height:1;text-align:center;list-style:none;background-color:var(--color-bg-popup);border:1px solid var(--color-neutral-3);border-radius:var(--border-radius-small);box-shadow:0 4px 10px #0000001a;transition:all .1s cubic-bezier(0,0,1,1);pointer-events:auto}.arco-message-icon{display:inline-block;margin-right:8px;color:var(--color-text-1);font-size:20px;vertical-align:middle;animation:arco-msg-fade .1s cubic-bezier(0,0,1,1),arco-msg-fade .4s cubic-bezier(.3,1.3,.3,1)}.arco-message-content{font-size:14px;color:var(--color-text-1);vertical-align:middle}.arco-message-info{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-info .arco-message-icon{color:rgb(var(--primary-6))}.arco-message-info .arco-message-content{color:var(--color-text-1)}.arco-message-success{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-success .arco-message-icon{color:rgb(var(--success-6))}.arco-message-success .arco-message-content{color:var(--color-text-1)}.arco-message-warning{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-warning .arco-message-icon{color:rgb(var(--warning-6))}.arco-message-warning .arco-message-content{color:var(--color-text-1)}.arco-message-error{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-error .arco-message-icon{color:rgb(var(--danger-6))}.arco-message-error .arco-message-content{color:var(--color-text-1)}.arco-message-loading{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-loading .arco-message-icon{color:rgb(var(--primary-6))}.arco-message-loading .arco-message-content{color:var(--color-text-1)}.arco-message-close-btn{margin-left:8px;color:var(--color-text-1);font-size:12px}.arco-message .arco-icon-hover.arco-message-icon-hover:before{width:20px;height:20px}.fade-message-enter-from,.fade-message-appear-from{opacity:0}.fade-message-enter-to,.fade-message-appear-to{opacity:1}.fade-message-enter-active,.fade-message-appear-active{transition:opacity .1s cubic-bezier(0,0,1,1)}.fade-message-leave-from{opacity:1}.fade-message-leave-to{opacity:0}.fade-message-leave-active{position:absolute}.flip-list-move{transition:transform .8s ease}@keyframes arco-msg-fade{0%{opacity:0}to{opacity:1}}@keyframes arco-msg-scale{0%{transform:scale(0)}to{transform:scale(1)}}:root{--c-brand: #3eaf7c;--c-brand-light: #4abf8a;--c-bg: #ffffff;--c-bg-light: #f3f4f5;--c-bg-lighter: #eeeeee;--c-bg-navbar: var(--c-bg);--c-bg-sidebar: var(--c-bg);--c-bg-arrow: #cccccc;--c-text: #2c3e50;--c-text-accent: var(--c-brand);--c-text-light: #3a5169;--c-text-lighter: #4e6e8e;--c-text-lightest: #6a8bad;--c-text-quote: #999999;--c-border: #eaecef;--c-border-dark: #dfe2e5;--c-tip: #42b983;--c-tip-bg: var(--c-bg-light);--c-tip-title: var(--c-text);--c-tip-text: var(--c-text);--c-tip-text-accent: var(--c-text-accent);--c-warning: #e7c000;--c-warning-bg: #fffae3;--c-warning-title: #ad9000;--c-warning-text: #746000;--c-warning-text-accent: var(--c-text);--c-danger: #cc0000;--c-danger-bg: #ffe0e0;--c-danger-title: #990000;--c-danger-text: #660000;--c-danger-text-accent: var(--c-text);--c-details-bg: #eeeeee;--c-badge-tip: var(--c-tip);--c-badge-warning: var(--c-warning);--c-badge-danger: var(--c-danger);--t-color: .3s ease;--t-transform: .3s ease;--code-bg-color: #282c34;--code-hl-bg-color: rgba(0, 0, 0, .66);--code-ln-color: #9e9e9e;--code-ln-wrapper-width: 3.5rem;--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;--font-family-code: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;--navbar-height: 3.6rem;--navbar-padding-v: .7rem;--navbar-padding-h: 1.5rem;--sidebar-width: 20rem;--sidebar-width-mobile: calc(var(--sidebar-width) * .82);--content-width: 740px;--homepage-width: 960px}html.dark{--c-brand: #3aa675;--c-brand-light: #349469;--c-bg: #22272e;--c-bg-light: #2b313a;--c-bg-lighter: #262c34;--c-text: #adbac7;--c-text-light: #96a7b7;--c-text-lighter: #8b9eb0;--c-text-lightest: #8094a8;--c-border: #3e4c5a;--c-border-dark: #34404c;--c-tip: #318a62;--c-warning: #ceab00;--c-warning-bg: #7e755b;--c-warning-title: #ceac03;--c-warning-text: #362e00;--c-danger: #940000;--c-danger-bg: #806161;--c-danger-title: #610000;--c-danger-text: #3a0000;--c-details-bg: #323843;--code-hl-bg-color: #363b46}@font-face{font-family:octicons-link;src:url(data:font/woff;charset=utf-8;base64,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) format("woff")}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;color:var(--c-text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol;font-size:14px;line-height:1.5;word-wrap:break-word;transition:background-color var(--t-color),border-color var(--t-color)}.g-emoji{display:inline-block;min-width:1ch;font-family:"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,serif;font-size:1em;font-style:normal!important;font-weight:400;line-height:1;vertical-align:-.075em}.markdown-body .pl-c{color:#6a737d}.markdown-body .pl-c1,.markdown-body .pl-s .pl-v{color:#005cc5}.markdown-body .pl-e,.markdown-body .pl-en{color:#6f42c1}.markdown-body .pl-smi,.markdown-body .pl-s .pl-s1{color:var(--c-text)}.markdown-body .pl-ent{color:#22863a}.markdown-body .pl-k{color:#d73a49}.markdown-body .pl-s,.markdown-body .pl-pds,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sre,.markdown-body .pl-sr .pl-sra{color:var(--c-text-lighter)}.markdown-body .pl-v,.markdown-body .pl-smw{color:#e36209}.markdown-body .pl-bu{color:#b31d28}.markdown-body .pl-ii{color:#fafbfc;background-color:#b31d28}.markdown-body .pl-c2{color:#fafbfc;background-color:#d73a49}.markdown-body .pl-c2:before{content:"^M"}.markdown-body .pl-sr .pl-cce{font-weight:700;color:#22863a}.markdown-body .pl-ml{color:#735c0f}.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms{font-weight:700;color:#005cc5}.markdown-body .pl-mi{font-style:italic;color:#24292e}.markdown-body .pl-mb{font-weight:700;color:#24292e}.markdown-body .pl-md{color:#b31d28;background-color:#ffeef0}.markdown-body .pl-mi1{color:#22863a;background-color:#f0fff4}.markdown-body .pl-mc{color:#e36209;background-color:#ffebda}.markdown-body .pl-mi2{color:#f6f8fa;background-color:#005cc5}.markdown-body .pl-mdr{font-weight:700;color:#6f42c1}.markdown-body .pl-ba{color:#586069}.markdown-body .pl-sg{color:#959da5}.markdown-body .pl-corl{text-decoration:underline;color:var(--c-text-lighter)}.markdown-body .octicon{display:inline-block;vertical-align:text-top;fill:currentColor}.markdown-body a{background-color:transparent;-webkit-text-decoration-skip:objects}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:inherit}.markdown-body strong{font-weight:bolder}.markdown-body h1{font-size:2em;margin:.67em 0}.markdown-body img{border-style:none}.markdown-body svg:not(:root){overflow:hidden}.markdown-body code,.markdown-body kbd,.markdown-body pre{font-family:monospace,monospace;font-size:1em}.markdown-body hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}.markdown-body input{font:inherit;margin:0}.markdown-body input{overflow:visible}.markdown-body [type=checkbox]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}.markdown-body *{-webkit-box-sizing:border-box;box-sizing:border-box}.markdown-body input{font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body a{color:#0366d6;text-decoration:none}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border:0;border-bottom:1px solid #dfe2e5}.markdown-body hr:before{display:table;content:""}.markdown-body hr:after{display:table;clear:both;content:""}.markdown-body table{border-spacing:0;border-collapse:collapse}.markdown-body td,.markdown-body th{padding:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:0;margin-bottom:0}.markdown-body h1{font-size:32px;font-weight:600}.markdown-body h2{font-size:24px;font-weight:600}.markdown-body h3{font-size:20px;font-weight:600}.markdown-body h4,.markdown-body h5{font-size:14px;font-weight:600}.markdown-body h6{font-size:12px;font-weight:600}.markdown-body p{margin-top:0;margin-bottom:10px}.markdown-body blockquote{margin:0}.markdown-body ul,.markdown-body ol{padding-left:0;margin-top:0;margin-bottom:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ul ul ol,.markdown-body ul ol ol,.markdown-body ol ul ol,.markdown-body ol ol ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body code{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:12px}.markdown-body pre{margin-top:0;margin-bottom:0;font:12px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}.markdown-body .octicon{vertical-align:text-bottom}.markdown-body .pl-0{padding-left:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .pl-3{padding-left:14px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body:before{display:table;content:""}.markdown-body:after{display:table;clear:both;content:""}.markdown-body>*:first-child{margin-top:0!important}.markdown-body>*:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:none}.markdown-body p,.markdown-body blockquote,.markdown-body ul,.markdown-body ol,.markdown-body dl,.markdown-body table,.markdown-body pre{margin-top:0;margin-bottom:14px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid var(--c-border)}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:solid 1px #c6cbd1;border-bottom-color:#959da5;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 #959da5;box-shadow:inset 0 -1px #959da5}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:14px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1{padding-bottom:.3em;font-size:2em;border-bottom:1px solid #eaecef}.markdown-body h2{padding-bottom:.3em;font-size:1.5em;border-bottom:1px solid #eaecef}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body ul,.markdown-body ol{padding-left:2em}.markdown-body ul ul,.markdown-body ul ol,.markdown-body ol ol,.markdown-body ol ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:14px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:14px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 14px;margin-bottom:14px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table th,.markdown-body table td{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;-webkit-box-sizing:content-box;box-sizing:content-box;background-color:#fff}.markdown-body code{padding:.2em 0;margin:0;font-size:85%;border-radius:3px}.markdown-body code:before,.markdown-body code:after{letter-spacing:-.2em;content:" "}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:14px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:14px;overflow:auto;font-size:85%;line-height:1.45;background-color:var(--c-tip-bg);border-radius:3px;color:var(--c-text);transition:background-color var(--t-color),border-color var(--t-color)}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0;color:var(--c-text)}.markdown-body pre code:before,.markdown-body pre code:after{content:normal}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:solid 1px #d1d5da;border-bottom-color:#c6cbd1;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 #c6cbd1;box-shadow:inset 0 -1px #c6cbd1}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle}.markdown-body hr{border-bottom-color:#eee}.gt-container{-webkit-box-sizing:border-box;box-sizing:border-box;font-size:14px}.gt-container *{-webkit-box-sizing:border-box;box-sizing:border-box}.gt-container a{color:var(--c-text-accent);transition:background-color var(--t-color),border-color var(--t-color)}.gt-container a.is--active{color:var(--c-text);cursor:default!important}.gt-container a.is--active:hover{color:var(--c-text-accent)}.gt-container .hide{display:none!important}.gt-container .gt-svg{display:inline-block;width:1em;height:1em;vertical-align:sub}.gt-container .gt-ico-arrdown{fill:var(--c-text)}.gt-container .gt-svg svg{width:100%;height:100%;fill:var(--c-text-accent)}.gt-container .gt-ico{display:inline-block}.gt-container .gt-ico-text{margin-left:.3125em}.gt-container .gt-ico-tip{font-size:.875em}.gt-container .gt-ico-github,.gt-container .gt-ico-github .gt-svg{width:100%;height:100%}.gt-container .gt-ico-github svg{fill:var(--c-text)}.gt-container .gt-spinner{position:relative}.gt-container .gt-spinner:before{content:"";-webkit-box-sizing:border-box;box-sizing:border-box;position:absolute;top:3px;width:.75em;height:.75em;margin-top:-.1875em;margin-left:-.375em;border-radius:50%;border:1px solid #fff;border-top-color:var(--c-text-accent);-webkit-animation:gt-kf-rotate .6s linear infinite;animation:gt-kf-rotate .6s linear infinite}.gt-container .gt-loader{position:relative;border:1px solid #999;-webkit-animation:ease gt-kf-rotate 1.5s infinite;animation:ease gt-kf-rotate 1.5s infinite;display:inline-block;font-style:normal;width:1.75em;height:1.75em;line-height:1.75em;border-radius:50%}.gt-container .gt-loader:before{content:"";position:absolute;display:block;top:0;left:50%;margin-top:-.1875em;margin-left:-.1875em;width:.375em;height:.375em;background-color:#999;border-radius:50%}.gt-container .gt-avatar{display:inline-block;width:3.125em;height:3.125em}@media (max-width: 479px){.gt-container .gt-avatar{width:2em;height:2em}}.gt-container .gt-avatar img{width:100%;height:auto;border-radius:3px}.gt-container .gt-avatar-github{width:3.125em;height:3.125em;cursor:pointer}@media (max-width: 479px){.gt-container .gt-avatar-github{width:2em;height:2em}}.gt-container .gt-btn{padding:.75em .95em;display:inline-block;line-height:1;text-decoration:none;white-space:nowrap;cursor:pointer;border:1px solid var(--c-text-accent);border-radius:5px;background-color:var(--c-brand);color:#fff;outline:none;font-size:.75em;transition:background-color var(--t-color),border-color var(--t-color)}.gt-container .gt-btn-text{font-weight:400}.gt-header-controls .gt-btn-public .gt-btn-text{color:var(--c-bg)}.gt-container .gt-btn-loading{position:relative;margin-left:.5em;display:inline-block;width:.75em;height:1em;vertical-align:top}.gt-container .gt-btn.is--disable{cursor:not-allowed;opacity:.5}.gt-container .gt-btn-login{margin-right:0;color:var(--c-bg)}.gt-container .gt-btn-login:hover{background-color:var(--c-brand-light);border-color:var(--c-brand)}.gt-container .gt-btn-preview{background-color:var(--c-bg);color:var(--c-brand);border-color:var(--c-brand);transition:background-color var(--t-color),border-color var(--t-color)}.gt-container .gt-btn-preview:hover{color:var(--c-bg);background-color:var(--c-brand-light)}.gt-container .gt-btn-public:hover,.gt-container .gt-btn-loadmore:hover{background-color:var(--c-brand-light);border-color:var(--c-brand)}.gt-container .gt-btn-loadmore{color:var(--c-bg)}.gt-container .gt-error{text-align:center;margin:.625em;color:#ff3860}.gt-container .gt-initing{padding:1.25em 0;text-align:center}.gt-container .gt-initing-text{margin:.625em auto;font-size:92%}.gt-container .gt-no-init{padding:1.25em 0;text-align:center}.gt-container .gt-link{border-bottom:1px dotted var(--c-text-accent)}.gt-container .gt-link-counts,.gt-container .gt-link-project{text-decoration:none}.gt-container .gt-meta{margin:1.25em 0;padding:1em 0;position:relative;border-bottom:1px solid var(--c-border);font-size:1em;transition:background-color var(--t-color),border-color var(--t-color)}.gt-container .gt-meta:before,.gt-container .gt-meta:after{content:" ";display:table}.gt-container .gt-meta:after{clear:both}.gt-container .gt-counts{margin:0 .625em 0 0}.gt-container .gt-user{float:right;margin:0;font-size:92%}.gt-container .gt-user-pic{width:14px;height:14px;vertical-align:top;margin-right:.5em}.gt-container .gt-user-inner{display:inline-block;cursor:pointer}.gt-container .gt-user .gt-ico{margin:0 0 0 .3125em}.gt-container .gt-user .gt-ico svg{fill:inherit}.gt-container .gt-user .is--poping .gt-ico svg{fill:var(--c-text-accent)}.gt-container .gt-version{color:#a1a1a1;margin-left:.375em}.gt-container .gt-copyright{margin:0 .9375em .5em;border-top:1px solid var(--c-border);padding-top:.5em}.gt-container .gt-popup{position:absolute;right:0;top:2.375em;background-color:var(--c-bg-navbar);display:block!important;border:1px solid var(--c-border);padding:.625em 0;font-size:.875em;letter-spacing:.5px;box-sizing:border-box;z-index:10}.gt-container .gt-popup .gt-action{cursor:pointer;display:block;margin:.5em 0;padding:0 1.125em;position:relative;text-decoration:none}.gt-container .gt-popup .gt-action.is--active:before{content:"";width:.25em;height:.25em;background:var(--c-text-accent);position:absolute;left:.5em;top:.4375em}.gt-container .gt-header{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex}.gt-container .gt-header-comment{-webkit-box-flex:1;-ms-flex:1;flex:1;padding-left:1.25em;width:90%}@media (max-width: 479px){.gt-container .gt-header-comment{padding-left:.875em}}.gt-container .gt-header-textarea{padding:.75em;display:block;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;min-height:5.125em;max-height:15em;border-radius:5px;border:1px solid var(--c-border);font-size:.875em;word-wrap:break-word;resize:vertical;background-color:var(--c-bg);outline:none;-webkit-transition:all .25s ease;transition:background-color var(--t-color),border-color var(--t-color)}.gt-header-textarea{color:var(--c-text)}.gt-container .gt-header-preview{padding:.75em;border-radius:5px;border:1px solid var(--c-border);background-color:var(--c-bg)}.gt-container .gt-header-controls{position:relative;margin:.75em 0 0}.gt-container .gt-header-controls:before,.gt-container .gt-header-controls:after{content:" ";display:table}.gt-container .gt-header-controls:after{clear:both}@media (max-width: 479px){.gt-container .gt-header-controls{margin:0}}.gt-container .gt-header-controls-tip{font-size:13px;color:var(--c-text-accent);text-decoration:none;vertical-align:sub}@media (max-width: 479px){.gt-container .gt-header-controls-tip{display:none}}.gt-container .gt-header-controls .gt-btn{float:right;margin-left:1.2em}@media (max-width: 479px){.gt-container .gt-header-controls .gt-btn{float:none;width:100%;margin:.75em 0 0}}.gt-container:after{content:"";position:fixed;bottom:100%;left:0;right:0;top:0;opacity:0}.gt-container.gt-input-focused{position:relative}.gt-container.gt-input-focused:after{content:"";position:fixed;bottom:0%;left:0;right:0;top:0;background:#000;opacity:.6;-webkit-transition:opacity .3s,bottom 0s;transition:opacity .3s,bottom 0s;z-index:9999}.gt-container.gt-input-focused .gt-header-comment{z-index:10000}.gt-container .gt-comments{padding-top:1.25em}.gt-container .gt-comments-null{text-align:center}.gt-container .gt-comments-controls{margin:1.25em 0;text-align:center}.gt-container .gt-comment{position:relative;padding:.625em 0;display:-webkit-box;display:-ms-flexbox;display:flex}.gt-container .gt-comment-content{-webkit-box-flex:1;-ms-flex:1;flex:1;margin-left:1.25em;padding:.75em 1em;background-color:var(--c-bg);overflow:auto;-webkit-transition:all ease .25s;border:1px solid var(--c-border);transition:background-color var(--t-color),border-color var(--t-color)}.gt-container .gt-comment-content{border-radius:5px}@media (max-width: 479px){.gt-container .gt-comment-content{margin-left:.875em;padding:.625em .75em}}.gt-container .gt-comment-header{margin-bottom:.75em;font-size:.875em;position:relative}.gt-container .gt-comment-block-1{float:right;height:1.375em;width:3.5em}.gt-container .gt-comment-block-2{float:right;height:1.375em;width:4em}.gt-container .gt-comment-username{font-weight:500;color:var(--c-text-accent);text-decoration:none}.gt-container .gt-comment-username:hover{text-decoration:underline}.gt-container .gt-comment-text,.gt-container .gt-comment-date{margin-left:.5em;color:#a1a1a1;font-size:.875em}.gt-container .gt-comment-like,.gt-container .gt-comment-edit,.gt-container .gt-comment-reply{position:absolute;height:1.375em}.gt-container .gt-comment-like:hover,.gt-container .gt-comment-edit:hover,.gt-container .gt-comment-reply:hover{cursor:pointer}.gt-container .gt-comment-like{top:0;right:2em}.gt-container .gt-comment-edit,.gt-container .gt-comment-reply{top:0;right:0}.gt-container .gt-comment-body{color:var(--c-text)}.gt-container .gt-comment-body .email-hidden-toggle a{display:inline-block;height:12px;padding:0 9px;font-size:12px;font-weight:600;line-height:6px;color:#444d56;text-decoration:none;vertical-align:middle;background:#dfe2e5;border-radius:1px}.gt-container .gt-comment-body .email-hidden-toggle a:hover{background-color:#c6cbd1}.gt-container .gt-comment-body .email-hidden-reply{display:none;white-space:pre-wrap}.gt-container .gt-comment-body .email-hidden-reply .email-signature-reply{padding:0 15px;margin:15px 0;color:#586069;border-left:4px solid #dfe2e5}.gt-container .gt-comment-body .email-hidden-reply.expanded{display:block}.gt-container .gt-comment-admin .gt-comment-content{background-color:var(--c-bg);border:1px solid var(--c-border)}@-webkit-keyframes gt-kf-rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes gt-kf-rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.gt-comment-body .snippet-clipboard-content pre code{color:var(--c-text)} diff --git a/assets/style.bd240186.css b/assets/style.bd240186.css deleted file mode 100644 index fc4ffa56..00000000 --- a/assets/style.bd240186.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-cyrillic.5f2c6c8c.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-cyrillic-ext.e75737ce.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-greek.d5a6d92a.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-greek-ext.ab0619bc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-latin.2ed14f66.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-latin-ext.0030eebd.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-vietnamese.14ce25a6.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-cyrillic.ea42a392.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-greek.8f4463c4.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-greek-ext.4fbe9427.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-latin.bd3b6f56.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-latin-ext.bd8920cc.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-vietnamese.6ce511fb.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Chinese Quotes;src:local("PingFang SC Regular"),local("PingFang SC"),local("SimHei"),local("Source Han Sans SC");unicode-range:U+2018,U+2019,U+201C,U+201D}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: rgba(60, 60, 67);--vp-c-text-2: rgba(60, 60, 67, .78);--vp-c-text-3: rgba(60, 60, 67, .56)}.dark{--vp-c-text-1: rgba(255, 255, 245, .86);--vp-c-text-2: rgba(235, 235, 245, .6);--vp-c-text-3: rgba(235, 235, 245, .38)}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Chinese Quotes", "Inter var", "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E")}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-green-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-green-1);--vp-code-line-diff-remove-color: var(--vp-c-red-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-red-1);--vp-code-line-warning-color: var(--vp-c-yellow-soft);--vp-code-line-error-color: var(--vp-c-red-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-brand-soft);--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-gray-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-brand-1);--vp-badge-tip-bg: var(--vp-c-brand-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);direction:ltr;font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{display:inline-block;margin:auto 2px -2px}mjx-container>svg{margin:auto}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-brand-1)}.custom-block.tip a:hover{color:var(--vp-c-brand-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code-light{display:none}html:not(.dark) .vp-code-dark{display:none}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s}.vp-doc blockquote>p{margin:0;font-size:16px;color:var(--vp-c-text-2);transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(.no-icon):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin-bottom:4px;text-align:center;letter-spacing:1px;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge[data-v-0d50132f]{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.vp-doc h1>.VPBadge[data-v-0d50132f]{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge[data-v-0d50132f]{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge[data-v-0d50132f]{vertical-align:middle}.vp-doc h4>.VPBadge[data-v-0d50132f],.vp-doc h5>.VPBadge[data-v-0d50132f],.vp-doc h6>.VPBadge[data-v-0d50132f]{vertical-align:middle;line-height:18px}.VPBadge.info[data-v-0d50132f]{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip[data-v-0d50132f]{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning[data-v-0d50132f]{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger[data-v-0d50132f]{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-90d3771d]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-90d3771d],.VPBackdrop.fade-leave-to[data-v-90d3771d]{opacity:0}.VPBackdrop.fade-leave-active[data-v-90d3771d]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-90d3771d]{display:none}}.NotFound[data-v-3b0106a5]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-3b0106a5]{padding:96px 32px 168px}}.code[data-v-3b0106a5]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-3b0106a5]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-3b0106a5]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-3b0106a5]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-3b0106a5]{padding-top:20px}.link[data-v-3b0106a5]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-3b0106a5]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-1772882b]{position:relative;z-index:1}.nested[data-v-1772882b]{padding-left:16px}.outline-link[data-v-1772882b]{display:block;line-height:28px;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s;font-weight:400}.outline-link[data-v-1772882b]:hover,.outline-link.active[data-v-1772882b]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-1772882b]{padding-left:13px}.VPDocAsideOutline[data-v-98b3e62f]{display:none}.VPDocAsideOutline.has-outline[data-v-98b3e62f]{display:block}.content[data-v-98b3e62f]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-98b3e62f]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-98b3e62f]{letter-spacing:.4px;line-height:28px;font-size:13px;font-weight:600}.VPDocAside[data-v-d3dab3d7]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-d3dab3d7]{flex-grow:1}.VPDocAside[data-v-d3dab3d7] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-d3dab3d7] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-d3dab3d7] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-43ed3de5]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-43ed3de5]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-d801cd4d]{margin-top:64px}.edit-info[data-v-d801cd4d]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-d801cd4d]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-d801cd4d]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-d801cd4d]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-d801cd4d]{margin-right:8px;width:14px;height:14px;fill:currentColor}.prev-next[data-v-d801cd4d]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-d801cd4d]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-d801cd4d]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-d801cd4d]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-d801cd4d]{margin-left:auto;text-align:right}.desc[data-v-d801cd4d]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-d801cd4d]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDocOutlineDropdown[data-v-3351e765]{margin-bottom:48px}.VPDocOutlineDropdown button[data-v-3351e765]{display:block;font-size:14px;font-weight:500;line-height:24px;border:1px solid var(--vp-c-border);padding:4px 12px;color:var(--vp-c-text-2);background-color:var(--vp-c-default-soft);border-radius:8px;transition:color .5s}.VPDocOutlineDropdown button[data-v-3351e765]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPDocOutlineDropdown button.open[data-v-3351e765]{color:var(--vp-c-text-1)}.icon[data-v-3351e765]{display:inline-block;vertical-align:middle;width:16px;height:16px;fill:currentColor}[data-v-3351e765] .outline-link{font-size:14px;font-weight:400}.open>.icon[data-v-3351e765]{transform:rotate(90deg)}.items[data-v-3351e765]{margin-top:12px;border-left:1px solid var(--vp-c-divider)}.VPDoc[data-v-eb54b406]{padding:32px 24px 96px;width:100%}.VPDoc .VPDocOutlineDropdown[data-v-eb54b406]{display:none}@media (min-width: 960px) and (max-width: 1279px){.VPDoc .VPDocOutlineDropdown[data-v-eb54b406]{display:block}}@media (min-width: 768px){.VPDoc[data-v-eb54b406]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-eb54b406]{padding:32px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-eb54b406]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-eb54b406]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-eb54b406]{display:flex;justify-content:center}.VPDoc .aside[data-v-eb54b406]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-eb54b406]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-eb54b406]{max-width:1104px}}.container[data-v-eb54b406]{margin:0 auto;width:100%}.aside[data-v-eb54b406]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-eb54b406]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-eb54b406]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 32px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-eb54b406]::-webkit-scrollbar{display:none}.aside-curtain[data-v-eb54b406]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-eb54b406]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 32px));padding-bottom:32px}.content[data-v-eb54b406]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-eb54b406]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-eb54b406]{order:1;margin:0;min-width:640px}}.content-container[data-v-eb54b406]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-eb54b406]{max-width:688px}.external-link-icon-enabled[data-v-eb54b406] :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):after{content:"";color:currentColor}.VPButton[data-v-a86ee6f3]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-a86ee6f3]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-a86ee6f3]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-a86ee6f3]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-a86ee6f3]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-a86ee6f3]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-a86ee6f3]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-a86ee6f3]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-a86ee6f3]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-a86ee6f3]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-a86ee6f3]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-a86ee6f3]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-a86ee6f3]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-26d78c9a]{display:none}.dark .VPImage.light[data-v-26d78c9a]{display:none}.VPHero[data-v-b88480c1]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-b88480c1]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-b88480c1]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-b88480c1]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-b88480c1]{flex-direction:row}}.main[data-v-b88480c1]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-b88480c1]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-b88480c1]{text-align:left}}@media (min-width: 960px){.main[data-v-b88480c1]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-b88480c1]{max-width:592px}}.name[data-v-b88480c1],.text[data-v-b88480c1]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-b88480c1],.VPHero.has-image .text[data-v-b88480c1]{margin:0 auto}.name[data-v-b88480c1]{color:var(--vp-home-hero-name-color)}.clip[data-v-b88480c1]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-b88480c1],.text[data-v-b88480c1]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-b88480c1],.text[data-v-b88480c1]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-b88480c1],.VPHero.has-image .text[data-v-b88480c1]{margin:0}}.tagline[data-v-b88480c1]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-b88480c1]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-b88480c1]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-b88480c1]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-b88480c1]{margin:0}}.actions[data-v-b88480c1]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-b88480c1]{justify-content:center}@media (min-width: 640px){.actions[data-v-b88480c1]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-b88480c1]{justify-content:flex-start}}.action[data-v-b88480c1]{flex-shrink:0;padding:6px}.image[data-v-b88480c1]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-b88480c1]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-b88480c1]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-b88480c1]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-b88480c1]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-b88480c1]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-b88480c1]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-b88480c1]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-b88480c1]{width:320px;height:320px}}[data-v-b88480c1] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-b88480c1] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-b88480c1] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-ec7504fd]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-ec7504fd]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-ec7504fd]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-ec7504fd]>.VPImage{margin-bottom:20px}.icon[data-v-ec7504fd]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-ec7504fd]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-ec7504fd]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-ec7504fd]{padding-top:8px}.link-text-value[data-v-ec7504fd]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-ec7504fd]{display:inline-block;margin-left:6px;width:14px;height:14px;fill:currentColor}.VPFeatures[data-v-4746fcfd]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-4746fcfd]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-4746fcfd]{padding:0 64px}}.container[data-v-4746fcfd]{margin:0 auto;max-width:1152px}.items[data-v-4746fcfd]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-4746fcfd]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-4746fcfd],.item.grid-4[data-v-4746fcfd],.item.grid-6[data-v-4746fcfd]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-4746fcfd],.item.grid-4[data-v-4746fcfd]{width:50%}.item.grid-3[data-v-4746fcfd],.item.grid-6[data-v-4746fcfd]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-4746fcfd]{width:25%}}.VPHome[data-v-f599c3dc]{padding-bottom:96px}.VPHome[data-v-f599c3dc] .VPHomeSponsors{margin-top:112px;margin-bottom:-128px}@media (min-width: 768px){.VPHome[data-v-f599c3dc]{padding-bottom:128px}}.VPContent[data-v-7787f055]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-7787f055]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-7787f055]{margin:0}@media (min-width: 960px){.VPContent[data-v-7787f055]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-7787f055]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-7787f055]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-855b7db4]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-855b7db4]{display:none}@media (min-width: 768px){.VPFooter[data-v-855b7db4]{padding:32px}}.container[data-v-855b7db4]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-855b7db4],.copyright[data-v-855b7db4]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-55e6f1d6]{padding:12px 20px 11px}.VPLocalNavOutlineDropdown button[data-v-55e6f1d6]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-55e6f1d6]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-55e6f1d6]{color:var(--vp-c-text-1)}.icon[data-v-55e6f1d6]{display:inline-block;vertical-align:middle;margin-left:2px;width:14px;height:14px;fill:currentColor}[data-v-55e6f1d6] .outline-link{font-size:14px;padding:2px 0}.open>.icon[data-v-55e6f1d6]{transform:rotate(90deg)}.items[data-v-55e6f1d6]{position:absolute;top:64px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}.header[data-v-55e6f1d6]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-55e6f1d6]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-55e6f1d6]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-55e6f1d6]{transition:all .2s ease-out}.flyout-leave-active[data-v-55e6f1d6]{transition:all .15s ease-in}.flyout-enter-from[data-v-55e6f1d6],.flyout-leave-to[data-v-55e6f1d6]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-6e4e13c1]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--vp-c-gutter);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-6e4e13c1]{position:fixed}.VPLocalNav.reached-top[data-v-6e4e13c1]{border-top-color:transparent}@media (min-width: 960px){.VPLocalNav[data-v-6e4e13c1]{display:none}}.menu[data-v-6e4e13c1]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-6e4e13c1]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-6e4e13c1]{padding:0 32px}}.menu-icon[data-v-6e4e13c1]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPOutlineDropdown[data-v-6e4e13c1]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-6e4e13c1]{padding:12px 32px 11px}}.VPSwitch[data-v-ad8fa6cf]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-ad8fa6cf]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-ad8fa6cf]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-ad8fa6cf]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-ad8fa6cf] svg{position:absolute;top:3px;left:3px;width:12px;height:12px;fill:var(--vp-c-text-2)}.dark .icon[data-v-ad8fa6cf] svg{fill:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-f31c77b6]{opacity:1}.moon[data-v-f31c77b6],.dark .sun[data-v-f31c77b6]{opacity:0}.dark .moon[data-v-f31c77b6]{opacity:1}.dark .VPSwitchAppearance[data-v-f31c77b6] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-82003167]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-82003167]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-df1d8bd6]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-df1d8bd6]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-df1d8bd6]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-df1d8bd6]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-bdc27f57]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-bdc27f57]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-bdc27f57]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-bdc27f57]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-3795579e]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-3795579e] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-3795579e] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-3795579e] .group:last-child{padding-bottom:0}.VPMenu[data-v-3795579e] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-3795579e] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-3795579e] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-3795579e] .action{padding-left:24px}.VPFlyout[data-v-419e6f76]{position:relative}.VPFlyout[data-v-419e6f76]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-419e6f76]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-419e6f76]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-419e6f76]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-419e6f76]{color:var(--vp-c-brand-2)}.VPFlyout:hover .menu[data-v-419e6f76],.button[aria-expanded=true]+.menu[data-v-419e6f76]{opacity:1;visibility:visible;transform:translateY(0)}.button[aria-expanded=false]+.menu[data-v-419e6f76]{opacity:0;visibility:hidden;transform:translateY(0)}.button[data-v-419e6f76]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-419e6f76]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-419e6f76]{margin-right:0;width:16px;height:16px;fill:currentColor}.text-icon[data-v-419e6f76]{margin-left:4px;width:14px;height:14px;fill:currentColor}.icon[data-v-419e6f76]{width:20px;height:20px;fill:currentColor;transition:fill .25s}.menu[data-v-419e6f76]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-d53a05fb]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-d53a05fb]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-d53a05fb]>svg{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-aea42604]{display:flex;justify-content:center}.VPNavBarExtra[data-v-edb32f2a]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-edb32f2a]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-edb32f2a]{display:none}}.trans-title[data-v-edb32f2a]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-edb32f2a],.item.social-links[data-v-edb32f2a]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-edb32f2a]{min-width:176px}.appearance-action[data-v-edb32f2a]{margin-right:-2px}.social-links-list[data-v-edb32f2a]{margin:-4px -8px}.VPNavBarHamburger[data-v-305e35d4]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-305e35d4]{display:none}}.container[data-v-305e35d4]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-305e35d4]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-305e35d4]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-305e35d4]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-305e35d4]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-305e35d4]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-305e35d4]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-305e35d4],.VPNavBarHamburger.active:hover .middle[data-v-305e35d4],.VPNavBarHamburger.active:hover .bottom[data-v-305e35d4]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-305e35d4],.middle[data-v-305e35d4],.bottom[data-v-305e35d4]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-305e35d4]{top:0;left:0;transform:translate(0)}.middle[data-v-305e35d4]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-305e35d4]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-0eb8cc79]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-0eb8cc79],.VPNavBarMenuLink[data-v-0eb8cc79]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-368cfbc9]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-368cfbc9]{display:flex}}/*! @docsearch/css 3.5.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;position:relative;padding:0 0 2px;border:0;top:-1px;width:20px}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}[class*=DocSearch]{--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-background: transparent;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand-1);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:0!important}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"Ctrl";font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"⌘"}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand-1);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-default-soft)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-3c6c0985]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-3c6c0985]{display:flex;align-items:center}}.title[data-v-d919d4a8]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-d919d4a8]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-d919d4a8]{border-bottom-color:var(--vp-c-divider)}}[data-v-d919d4a8] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-780fc638]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-780fc638]{display:flex;align-items:center}}.title[data-v-780fc638]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-e4fc9f8b]{position:relative;border-bottom:1px solid transparent;padding:0 8px 0 24px;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap}@media (min-width: 768px){.VPNavBar[data-v-e4fc9f8b]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar[data-v-e4fc9f8b]{padding:0}.VPNavBar[data-v-e4fc9f8b]:not(.has-sidebar):not(.top){border-bottom-color:var(--vp-c-gutter);background-color:var(--vp-nav-bg-color)}}.container[data-v-e4fc9f8b]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-e4fc9f8b],.container>.content[data-v-e4fc9f8b]{pointer-events:none}.container[data-v-e4fc9f8b] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-e4fc9f8b]{max-width:100%}}.title[data-v-e4fc9f8b]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-e4fc9f8b]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-e4fc9f8b]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-e4fc9f8b]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-e4fc9f8b]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-e4fc9f8b]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-e4fc9f8b]{display:flex;justify-content:flex-end;align-items:center;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.top) .content-body[data-v-e4fc9f8b]{position:relative;background-color:var(--vp-nav-bg-color)}}@media (max-width: 767px){.content-body[data-v-e4fc9f8b]{column-gap:.5rem}}.menu+.translations[data-v-e4fc9f8b]:before,.menu+.appearance[data-v-e4fc9f8b]:before,.menu+.social-links[data-v-e4fc9f8b]:before,.translations+.appearance[data-v-e4fc9f8b]:before,.appearance+.social-links[data-v-e4fc9f8b]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-e4fc9f8b]:before,.translations+.appearance[data-v-e4fc9f8b]:before{margin-right:16px}.appearance+.social-links[data-v-e4fc9f8b]:before{margin-left:16px}.social-links[data-v-e4fc9f8b]{margin-right:-8px}@media (min-width: 960px){.VPNavBar.has-sidebar .curtain[data-v-e4fc9f8b]{position:absolute;right:0;bottom:-31px;width:calc(100% - var(--vp-sidebar-width));height:32px}.VPNavBar.has-sidebar .curtain[data-v-e4fc9f8b]:before{display:block;width:100%;height:32px;background:linear-gradient(var(--vp-c-bg),transparent 70%);content:""}}@media (min-width: 1440px){.VPNavBar.has-sidebar .curtain[data-v-e4fc9f8b]{width:calc(100% - ((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width)))}}.VPNavScreenAppearance[data-v-14d6533b]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-14d6533b]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-100771e7]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-100771e7]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-bb6df54f]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-bb6df54f]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-c3cb64a0]{display:block}.title[data-v-c3cb64a0]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-ba0cbdca]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-ba0cbdca]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-ba0cbdca]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-ba0cbdca]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-ba0cbdca]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-ba0cbdca]{transform:rotate(45deg)}.button[data-v-ba0cbdca]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-ba0cbdca]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-ba0cbdca]{width:14px;height:14px;fill:var(--vp-c-text-2);transition:fill .5s,transform .25s}.group[data-v-ba0cbdca]:first-child{padding-top:0}.group+.group[data-v-ba0cbdca],.group+.item[data-v-ba0cbdca]{padding-top:4px}.VPNavScreenTranslations[data-v-2a5206d0]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-2a5206d0]{height:auto}.title[data-v-2a5206d0]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-2a5206d0]{width:16px;height:16px;fill:currentColor}.icon.lang[data-v-2a5206d0]{margin-right:8px}.icon.chevron[data-v-2a5206d0]{margin-left:4px}.list[data-v-2a5206d0]{padding:4px 0 0 24px}.link[data-v-2a5206d0]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-a794a04d]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 1px);right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .5s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-a794a04d],.VPNavScreen.fade-leave-active[data-v-a794a04d]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-a794a04d],.VPNavScreen.fade-leave-active .container[data-v-a794a04d]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-a794a04d],.VPNavScreen.fade-leave-to[data-v-a794a04d]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-a794a04d],.VPNavScreen.fade-leave-to .container[data-v-a794a04d]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-a794a04d]{display:none}}.container[data-v-a794a04d]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-a794a04d],.menu+.appearance[data-v-a794a04d],.translations+.appearance[data-v-a794a04d]{margin-top:24px}.menu+.social-links[data-v-a794a04d]{margin-top:16px}.appearance+.social-links[data-v-a794a04d]{margin-top:16px}.VPNav[data-v-f92d2e4c]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-f92d2e4c]{position:fixed}}.VPSidebarItem.level-0[data-v-c543663c]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-c543663c]{padding-bottom:10px}.item[data-v-c543663c]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-c543663c]{cursor:pointer}.indicator[data-v-c543663c]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-c543663c],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-c543663c],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-c543663c],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-c543663c]{background-color:var(--vp-c-brand-1)}.link[data-v-c543663c]{display:flex;align-items:center;flex-grow:1}.text[data-v-c543663c]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-c543663c]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-c543663c],.VPSidebarItem.level-2 .text[data-v-c543663c],.VPSidebarItem.level-3 .text[data-v-c543663c],.VPSidebarItem.level-4 .text[data-v-c543663c],.VPSidebarItem.level-5 .text[data-v-c543663c]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-c543663c],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-c543663c],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-c543663c],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-c543663c],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-c543663c],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-c543663c]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-c543663c],.VPSidebarItem.level-1.has-active>.item>.text[data-v-c543663c],.VPSidebarItem.level-2.has-active>.item>.text[data-v-c543663c],.VPSidebarItem.level-3.has-active>.item>.text[data-v-c543663c],.VPSidebarItem.level-4.has-active>.item>.text[data-v-c543663c],.VPSidebarItem.level-5.has-active>.item>.text[data-v-c543663c],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-c543663c],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-c543663c],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-c543663c],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-c543663c],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-c543663c],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-c543663c]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-c543663c],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-c543663c],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-c543663c],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-c543663c],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-c543663c],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-c543663c]{color:var(--vp-c-brand-1)}.caret[data-v-c543663c]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-c543663c]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-c543663c]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-c543663c]{width:18px;height:18px;fill:currentColor;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-c543663c]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-c543663c],.VPSidebarItem.level-2 .items[data-v-c543663c],.VPSidebarItem.level-3 .items[data-v-c543663c],.VPSidebarItem.level-4 .items[data-v-c543663c],.VPSidebarItem.level-5 .items[data-v-c543663c]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-c543663c]{display:none}.VPSidebar[data-v-9b5436d7]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-9b5436d7]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-9b5436d7]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-9b5436d7]{z-index:1;padding-top:var(--vp-nav-height);padding-bottom:128px;width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-9b5436d7]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-9b5436d7]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-9b5436d7]{outline:0}.group+.group[data-v-9b5436d7]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-9b5436d7]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSkipLink[data-v-197f0fa6]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-197f0fa6]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-197f0fa6]{top:14px;left:16px}}.Layout[data-v-bb676018]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-cf5a4148]{border-top:1px solid var(--vp-c-gutter);padding:88px 24px 96px;background-color:var(--vp-c-bg)}.container[data-v-cf5a4148]{margin:0 auto;max-width:1152px}.love[data-v-cf5a4148]{margin:0 auto;width:28px;height:28px;color:var(--vp-c-text-3)}.icon[data-v-cf5a4148]{width:28px;height:28px;fill:currentColor}.message[data-v-cf5a4148]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-cf5a4148]{padding-top:32px}.action[data-v-cf5a4148]{padding-top:40px;text-align:center}.VPTeamPage[data-v-2119ee1b]{padding-bottom:96px}@media (min-width: 768px){.VPTeamPage[data-v-2119ee1b]{padding-bottom:128px}}.VPTeamPageSection+.VPTeamPageSection[data-v-2119ee1b-s],.VPTeamMembers+.VPTeamPageSection[data-v-2119ee1b-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-2119ee1b-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-2119ee1b-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-2119ee1b-s],.VPTeamMembers+.VPTeamPageSection[data-v-2119ee1b-s]{margin-top:96px}}.VPTeamMembers[data-v-2119ee1b-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-2119ee1b-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-2119ee1b-s]{padding:0 64px}}.VPTeamPageTitle[data-v-ec34449f]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-ec34449f]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-ec34449f]{padding:80px 64px 48px}}.title[data-v-ec34449f]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-ec34449f]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-ec34449f]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-ec34449f]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-65e07c35]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-65e07c35]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-65e07c35]{padding:0 64px}}.title[data-v-65e07c35]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-65e07c35]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-65e07c35]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-65e07c35]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-65e07c35]{padding-top:40px}.VPTeamMembersItem[data-v-af6b5bed]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-af6b5bed]{padding:32px}.VPTeamMembersItem.small .data[data-v-af6b5bed]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-af6b5bed]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-af6b5bed]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-af6b5bed]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-af6b5bed]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-af6b5bed]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-af6b5bed]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-af6b5bed]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-af6b5bed]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-af6b5bed]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-af6b5bed]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-af6b5bed]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-af6b5bed]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-af6b5bed]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-af6b5bed]{text-align:center}.avatar[data-v-af6b5bed]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-af6b5bed]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-af6b5bed]{margin:0;font-weight:600}.affiliation[data-v-af6b5bed]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-af6b5bed]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-af6b5bed]:hover{color:var(--vp-c-brand-1)}.desc[data-v-af6b5bed]{margin:0 auto}.desc[data-v-af6b5bed] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-af6b5bed]{display:flex;justify-content:center;height:56px}.sp-link[data-v-af6b5bed]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-af6b5bed]:hover,.sp .sp-link.link[data-v-af6b5bed]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-af6b5bed]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPTeamMembers.small .container[data-v-19b1d5cb]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-19b1d5cb]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-19b1d5cb]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-19b1d5cb]{max-width:876px}.VPTeamMembers.medium .container[data-v-19b1d5cb]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-19b1d5cb]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-19b1d5cb]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-19b1d5cb]{max-width:760px}.container[data-v-19b1d5cb]{display:grid;gap:24px;margin:0 auto;max-width:1152px}#nprogress{pointer-events:none}#nprogress .bar{background:var(--vp-c-brand);position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px var(--vp-c-brand),0 0 5px var(--vp-c-brand);opacity:1;-webkit-transform:rotate(3deg) translate(0px,-4px);-ms-transform:rotate(3deg) translate(0px,-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:var(--vp-c-brand);border-left-color:var(--vp-c-brand);border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .spinner,.nprogress-custom-parent #nprogress .bar{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:root{--vp-twoslash-c-annotation-fg: var(--vp-c-text-1);--vp-twoslash-c-brand: var(--vp-c-brand);--vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);--vp-twoslash-c-error-fg: var(--vp-c-text-1);--vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);--vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);--vp-twoslash-c-logger-fg: var(--vp-c-text-1);--vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);--vp-twoslash-c-logger-log-fg: var(--vp-c-gray);--vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);--vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);--vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);--vp-twoslash-c-lsp-border: var(--vp-c-divider);--vp-twoslash-c-lsp-fg: var(--vp-c-text-1);--vp-twoslash-c-lsp-underline: var(--vp-c-text-2) ;--vp-twoslash-lsp-shadow: var(--vp-shadow-2);--vp-twoslash-c-query-bg: var(--vp-c-mute-darker);--vp-twoslash-c-query-fg-2: var(--vp-c-text-2);--vp-twoslash-c-query-fg: var(--vp-c-text-1)}pre.shiki.twoslash,pre.shiki.twoslash code{background-color:unset!important;color:unset!important}@media (min-width: 640px){.vp-doc div[class*=language-],pre.shiki.twoslash{overflow:visible}}pre.shiki .language-id,.language-twoslash{display:none}pre .error,pre .error-behind{display:block;margin-bottom:4px;margin-left:-24px;margin-top:8px;padding:6px 6px 6px 24px;white-space:pre-wrap;width:100%}pre .error{position:absolute;background-color:var(--vp-twoslash-c-error-bg);display:flex;align-items:center;color:var(--vp-twoslash-c-error-fg)}pre .error .code{display:none}pre .error-behind{-webkit-user-select:none;user-select:none;visibility:transparent;color:transparent}pre .arrow{background-color:var(--vp-twoslash-c-query-bg);position:relative;top:-6px;margin-left:.1rem;border-left:1px solid var(--vp-twoslash-c-query-bg);border-top:1px solid var(--vp-twoslash-c-query-bg);transform:translateY(25%) rotate(45deg);height:8px;width:8px}pre .popover{color:var(--vp-twoslash-c-query-fg);margin-bottom:10px;background-color:var(--vp-twoslash-c-query-bg);display:inline-block;line-height:inherit;padding:0 .5rem .3rem;margin-top:8px;border-radius:3px;max-width:575px;white-space:pre-wrap}pre.twoslash:hover data-lsp{border-color:var(--vp-twoslash-c-lsp-underline)}pre.twoslash data-lsp:hover:before{content:attr(lsp);position:absolute;transform:translateY(1.15rem);color:var(--vp-twoslash-c-lsp-fg);background-color:var(--vp-twoslash-c-lsp-bg);border:1px solid var(--vp-twoslash-c-lsp-border);box-shadow:var(--vp-twoslash-lsp-shadow);text-align:left;padding:5px 8px;border-radius:3px;font-size:14px;white-space:pre-wrap;z-index:100}data-lsp{border-bottom:1px dotted transparent;transition-timing-function:ease;transition:border-color .3s}@media (prefers-reduced-motion: reduce){data-lsp{transition:none}}pre data-err{background:url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23c94824'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left;padding-bottom:3px}pre .code-container>a{position:absolute;right:9px;bottom:8px;border-radius:2px;background-image:url("data:image/svg+xml,%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3ETypeScript%3C/title%3E%3Cpath fill='%233078c6' d='M1.125 0C.502 0 0 .502 0 1.125v21.75C0 23.498.502 24 1.125 24h21.75c.623 0 1.125-.502 1.125-1.125V1.125C24 .502 23.498 0 22.875 0zm17.363 9.75c.612 0 1.154.037 1.627.111a6.38 6.38 0 0 1 1.306.34v2.458a3.95 3.95 0 0 0-.643-.361 5.093 5.093 0 0 0-.717-.26 5.453 5.453 0 0 0-1.426-.2c-.3 0-.573.028-.819.086a2.1 2.1 0 0 0-.623.242c-.17.104-.3.229-.393.374a.888.888 0 0 0-.14.49c0 .196.053.373.156.529.104.156.252.304.443.444s.423.276.696.41c.273.135.582.274.926.416.47.197.892.407 1.266.628.374.222.695.473.963.753.268.279.472.598.614.957.142.359.214.776.214 1.253 0 .657-.125 1.21-.373 1.656a3.033 3.033 0 0 1-1.012 1.085 4.38 4.38 0 0 1-1.487.596c-.566.12-1.163.18-1.79.18a9.916 9.916 0 0 1-1.84-.164 5.544 5.544 0 0 1-1.512-.493v-2.63a5.033 5.033 0 0 0 3.237 1.2c.333 0 .624-.03.872-.09.249-.06.456-.144.623-.25.166-.108.29-.234.373-.38a1.023 1.023 0 0 0-.074-1.089 2.12 2.12 0 0 0-.537-.5 5.597 5.597 0 0 0-.807-.444 27.72 27.72 0 0 0-1.007-.436c-.918-.383-1.602-.852-2.053-1.405-.45-.553-.676-1.222-.676-2.005 0-.614.123-1.141.369-1.582.246-.441.58-.804 1.004-1.089a4.494 4.494 0 0 1 1.47-.629 7.536 7.536 0 0 1 1.77-.201zm-15.113.188h9.563v2.166H9.506v9.646H6.789v-9.646H3.375z'/%3E%3C/svg%3E");background-color:#fff;width:20px;height:20px;color:transparent;text-decoration:none;opacity:0;transition-timing-function:ease;transition:opacity .3s}pre .code-container>a:hover{color:transparent}@media (prefers-reduced-motion: reduce){pre .code-container>a{transition:none}}pre .code-container:hover a{opacity:1}pre .inline-completions ul.dropdown{display:inline-block;position:absolute;width:240px;background-color:var(--vp-twoslash-c-query-bg);color:var(--vp-twoslash-c-query-fg-2);font-family:var(--code-font);margin:0;padding:0;border-left:4px solid var(--vp-twoslash-c-query-bg)}pre .inline-completions ul.dropdown:before{background-color:var(--vp-twoslash-c-query-fg);width:2px;position:absolute;top:-1.2rem;left:-3px;height:17px;content:" "}pre .inline-completions ul.dropdown li{overflow-x:hidden;padding-left:4px;margin-bottom:4px}pre .inline-completions ul.dropdown li.deprecated{text-decoration:line-through}pre .inline-completions ul.dropdown li span.result-found{color:var(--vp-twoslash-c-query-fg);font-weight:700}pre .inline-completions ul.dropdown li span.result{width:100px;color:var(--vp-twoslash-c-query-fg-2);display:inline-block}pre code[class*=language-]{all:unset!important}pre code[class*=language-] pre{padding:0!important}div[class*=language-] pre:not(.shiki){position:unset!important;white-space:inherit!important}pre .logger{display:flex;align-items:center;color:var(--vp-twoslash-c-logger-fg);padding:6px 6px 6px 8px;width:100%;white-space:pre-wrap}pre .logger svg{margin-right:9px}pre .logger.error-log{background-color:var(--vp-twoslash-c-logger-error-bg)}pre .logger.error-log svg path{fill:var(--vp-twoslash-c-logger-error-fg);stroke:var(--vp-twoslash-c-logger-error-fg)}pre .logger.warn-log{background-color:var(--vp-twoslash-c-logger-warn-bg)}pre .logger.warn-log svg path{fill:var(--vp-twoslash-c-logger-warn-fg);stroke:var(--vp-twoslash-c-logger-warn-fg)}pre .logger.log-log{background-color:var(--vp-twoslash-c-logger-log-bg)}pre .logger.log-log svg path,pre .logger.log-log svg line{fill:var(--vp-twoslash-c-logger-log-fg);stroke:var(--vp-twoslash-c-logger-log-fg)}pre .logger.log-log svg{margin-left:6px;margin-right:9px}.tag-container,.tag-container pre{position:unset!important}.tag-container .twoslash-annotation{position:absolute;right:-10px;width:200px;color:var(--vp-twoslash-c-brand);z-index:100}.tag-container .twoslash-annotation p{text-align:left;font-size:.8rem;line-height:.9rem}.tag-container .twoslash-annotation svg{float:left;margin-left:-44px}.tag-container .twoslash-annotation.left{right:auto;left:-200px}.tag-container .twoslash-annotation.left svg{float:right;margin-right:-5px}.tag-container .twoslash-annotation svg path{stroke:var(--vp-twoslash-c-annotation-fg)}pre.shiki:hover .dim{opacity:1}pre.shiki div.dim{opacity:.5}pre.shiki div.dim,pre.shiki div.highlight{margin:0;padding:0}pre.shiki div.highlight{opacity:1;background-color:var(--vp-c-mute-light)}pre.shiki div.line{min-height:1rem}pre.shiki span.line.highlighted{background-color:var(--vp-code-line-highlight-color)}pre code{-webkit-overflow-scrolling:touch}pre code a{text-decoration:none}pre .query{margin-bottom:10px;color:#137998;display:inline-block}*{scrollbar-color:var(--vp-c-divider-light) var(--vp-button-alt-bg);scrollbar-width:thin}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:var(--vp-c-mute)}::-webkit-scrollbar-thumb:hover{background:var(--vp-button-alt-hover-bg)}::-webkit-scrollbar-track{background:var(--vp-button-alt-bg)}::-webkit-scrollbar-corner{background:transparent}.katex{font-size:1.05em;direction:ltr}.katex-display{overflow:auto hidden;-webkit-overflow-scrolling:touch;padding-top:.2em;padding-bottom:.2em}.katex-display::-webkit-scrollbar{height:3px}.katex-display .katex{font-size:1.21em}.katex-error{color:red}.medium-zoom-image{z-index:21}.medium-zoom-image{align-items:center}.VPDoc .content-container img{border-radius:5px}.heart{animation:heart 5s ease infinite;color:red}@keyframes heart{0%{transform:scale(1)}5%{transform:scale(1.25)}20%{transform:scale(1)}30%{transform:scale(1)}35%{transform:scale(1.25)}50%{transform:scale(1)}55%{transform:scale(1.25)}70%{transform:scale(1)}}.coffee{color:#580d0d}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img.VPImage.image-src{width:300px}.vp-doc>div{width:100%}@media (min-width: 1440px){.VPDoc.has-aside .content-container.content-container{max-width:100%}}.vp-doc p a+a{margin-left:17px}@media (max-width: 1080px){:root{--vp-sidebar-width: 260px}.VPNav .DocSearch-Button-Placeholder{display:none}.VPNav .VPNavBarMenuLink,.VPNav .VPNavBarMenuGroup .button{padding-left:10px;padding-right:10px}}@media (max-width: 992px){.VPNav .VPNavBar{padding-left:24px;padding-right:24px}.VPNav .VPNavBarMenuLink,.VPNav .VPNavBarMenuGroup .button{padding-left:8px;padding-right:8px}}@media (max-width: 800px){.VPNav .VPNavBarSearch{padding-left:16px}.VPNav .VPNavBarMenuLink,.VPNav .VPNavBarMenuGroup .button{padding-left:6px;padding-right:6px}}.VPMenuGroup .title{white-space:nowrap}.DocSearch-Logo{display:none}.link-preview-widget{display:table;width:100%;border:2px solid rgba(55,53,47,.16);border-radius:5px}.link-preview-widget-title{font-size:16px;font-weight:700;display:-webkit-box;overflow:hidden;margin-bottom:8px;word-break:break-all;-webkit-box-orient:vertical;-webkit-line-clamp:2}.link-preview-widget-description{font-size:12px;font-style:normal;line-height:1.5;display:-webkit-box;overflow:hidden;max-height:3em;margin-bottom:4px;word-break:break-all;color:#37352fa6;-webkit-box-orient:vertical;-webkit-line-clamp:2}.link-preview-widget-url{font-size:12px;font-style:normal;line-height:1.5;display:block;margin-bottom:0;color:#37352fa6}.link-preview-widget>a{text-decoration:none!important;display:table-cell;flex-direction:column;padding:16px;cursor:pointer;vertical-align:middle;color:inherit;background-color:transparent;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;flex:1;transition:background-color .2s ease-in-out;border-radius:5px}.link-preview-widget>a:hover{background-color:var(--vp-custom-block-tip-bg)}.link-preview-widget-image{width:260px;min-width:220px;height:150px;padding:0;vertical-align:middle;border-left:1px rgba(55,53,47,.16) #f2f2f2;border-radius:5px;background-repeat:no-repeat;background-position:50%;background-size:cover;-webkit-box-flex:0;flex:0}html.dark .link-preview-widget{display:table;width:100%;border:2px solid rgba(200,202,208,.16);border-radius:5px}html.dark .link-preview-widget-title{font-size:16px;font-weight:700;display:-webkit-box;overflow:hidden;margin-bottom:8px;word-break:break-all;-webkit-box-orient:vertical;-webkit-line-clamp:2}html.dark .link-preview-widget-description{font-size:12px;font-style:normal;line-height:1.5;display:-webkit-box;overflow:hidden;max-height:3em;margin-bottom:4px;word-break:break-all;color:var(--vp-c-text-2);-webkit-box-orient:vertical;-webkit-line-clamp:2}html.dark .link-preview-widget-url{font-size:12px;font-style:normal;line-height:1.5;display:block;margin-bottom:0;color:var(--vp-c-text-2)}html.dark .link-preview-widget>a{text-decoration:none!important;display:table-cell;flex-direction:column;padding:16px;cursor:pointer;vertical-align:middle;color:inherit;background-color:transparent;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;flex:1;transition:background-color .2s ease-in-out}html.dark .link-preview-widget>a:hover{background-color:var(--vp-custom-block-tip-bg)}html.dark .link-preview-widget-image{width:260px;min-width:220px;height:150px;padding:0;vertical-align:middle;border-left:1px rgba(200,202,208,.16) #f2f2f2;border-radius:5px;background-repeat:no-repeat;background-position:50%;background-size:cover;-webkit-box-flex:0;flex:0}.vp-doc h2{border-top:0px;margin-top:10px}.VPMenuLink .link{line-height:28px!important}.VPSidebarGroup .link{padding:3px 0!important}.VPTeamPageTitle .title{line-height:32px;font-size:24px;opacity:.5}.VPTeamPageTitle .lead{font-size:14px;opacity:.4}.medium-zoom-overlay{z-index:20}.m-home-layout .image-src:hover{transform:translate(-50%,-50%) rotate(666turn);transition:transform 59s 1s cubic-bezier(.3,0,.8,1)}.m-home-layout .details small{opacity:.8}.m-home-layout .item:last-child .details{display:flex;justify-content:flex-end;align-items:end}:root{--vp-home-hero-name-color: transparent;--vp-home-hero-name-background: -webkit-linear-gradient(315deg, #42d392 25%, #647eff);--vp-home-hero-image-background-image: linear-gradient(-45deg, #42d392 50%, #47caff 50%);--vp-home-hero-image-filter: blur(40px)}@media (min-width: 640px){:root{--vp-home-hero-image-filter: blur(56px)}}@media (min-width: 960px){:root{--vp-home-hero-image-filter: blur(72px)}}:root:not(.dark){--vp-code-block-bg: rgba(125, 125, 125, .04);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-code-hover-bg: rgba(125, 125, 125, .1);--vp-code-tab-divider: var(--vp-c-mute-dark);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-c-text-dark-3: rgba(180, 180, 180, .7)}:root.dark{--vp-code-block-bg: rgba(0, 0, 0, .2);--vp-c-text-dark-3: rgba(235, 235, 235, .38)}html:not(.dark) pre.shiki[class*=dark]{display:none}html:not(.dark) pre.shiki[class*=light]{display:block}html.dark pre.shiki[class*=dark]{display:block}html.dark pre.shiki[class*=light]{display:none}:root{--vp-twoslash-c-annotation-fg: var(--vp-c-text-1);--vp-twoslash-c-brand: var(--vp-c-brand);--vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);--vp-twoslash-c-error-fg: var(--vp-c-text-1);--vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);--vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);--vp-twoslash-c-logger-fg: var(--vp-c-text-1);--vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);--vp-twoslash-c-logger-log-fg: var(--vp-c-gray);--vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);--vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);--vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);--vp-twoslash-c-lsp-border: var(--vp-c-divider);--vp-twoslash-c-lsp-fg: var(--vp-c-text-1);--vp-twoslash-c-lsp-underline: var(--vp-c-text-2);--vp-twoslash-lsp-shadow: var(--vp-shadow-2);--vp-twoslash-c-query-bg: var(--vp-c-mute-dark);--vp-twoslash-c-query-fg-2: var(--vp-c-text-2);--vp-twoslash-c-query-fg: var(--vp-c-text-1)}.vp-code-group .tabs label{background-color:transparent;--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-active-text-color: var(--vp-c-text-1)}.home-content h2{margin-top:2rem;font-size:1.35rem;border-bottom:none;margin-bottom:0}img.resizable-img{width:unset;height:unset}*,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgba(0,0,0,0);--un-ring-shadow:0 0 rgba(0,0,0,0);--un-shadow-inset: ;--un-shadow:0 0 rgba(0,0,0,0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgba(0,0,0,0);--un-ring-shadow:0 0 rgba(0,0,0,0);--un-shadow-inset: ;--un-shadow:0 0 rgba(0,0,0,0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.static{position:static}.grid{display:grid}.m21{margin:5.25rem}.m9{margin:2.25rem}[ma=""]{margin:auto}.my{margin-top:1rem;margin-bottom:1rem}.mb{margin-bottom:1rem}.mb-\[12px\]{margin-bottom:12px}.me{margin-inline-end:1rem}.ms{margin-inline-start:1rem}.mt-\[24px\]{margin-top:24px}.inline{display:inline}.block,[block=""]{display:block}.inline-block{display:inline-block}.contents,[contents=""]{display:contents}.hidden{display:none}.h\$\.{height:var(--\.)}.h1{height:.25rem}.h2{height:.5rem}.h3{height:.75rem}.h4{height:1rem}.h5{height:1.25rem}.h6{height:1.5rem}.max-w-\[85\%\]{max-width:85%}.w-full{width:100%}.flex{display:flex}.flex-shrink{flex-shrink:1}.flex-grow{flex-grow:1}.flex-wrap{flex-wrap:wrap}.table{display:table}.transform{transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.items-center{align-items:center}.gap-\[12px\]{gap:12px}.gap-\[4px\]{gap:4px}.b,.b-1,.border,[b=""]{border-width:1px}.b\!{border-width:1px!important}.border-b-1{border-bottom-width:1px}.border-\[var\(--vp-c-divider\)\]{border-color:var(--vp-c-divider)}.border-b-solid{border-bottom-style:solid}[stroke-width~="2"]{stroke-width:2px}.px{padding-left:1rem;padding-right:1rem}.py{padding-top:1rem;padding-bottom:1rem}.pb-\[12px\]{padding-bottom:12px}.pl{padding-left:1rem}.pt{padding-top:1rem}.pie{padding-inline-end:1rem}.pie\!{padding-inline-end:1rem!important}.uppercase,[uppercase=""]{text-transform:uppercase}.lowercase,[lowercase=""]{text-transform:lowercase}.italic{font-style:italic}.tab{-moz-tab-size:4;-o-tab-size:4;tab-size:4}.outline{outline-style:solid}.blur{--un-blur:blur(8px);filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.filter{filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.ease{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-height:90px}.copyright[data-v-ddda9334]{border-color:var(--vp-custom-block-tip-border);border-style:solid;border-width:1px;background-color:var(--vp-custom-block-tip-bg);border-radius:6px;color:var(--vp-c-text-2);font-size:15px;margin-top:50px}.copyright .content[data-v-ddda9334]{padding:13px 16px}.copyright .content .item[data-v-ddda9334]{margin-bottom:5px;word-break:break-word;line-height:22px}.copyright .content .item .icon[data-v-ddda9334]{display:inline-block;height:16px;width:16px;margin-right:.375rem;vertical-align:-2.5px}a[data-v-ddda9334]{font-weight:400;color:var(--vp-c-text-2)}a[data-v-ddda9334]:hover{color:var(--vp-c-brand)}.copyrightText[data-v-ddda9334]{font-weight:700}/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{margin:0}main{display:block}h1{margin:.67em 0;font-size:2em}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-size:1em;font-family:monospace,monospace}a{background-color:transparent}abbr[title]{text-decoration:underline;text-decoration:underline dotted;border-bottom:none}b,strong{font-weight:bolder}code,kbd,samp{font-size:1em;font-family:monospace,monospace}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{margin:0;font-size:100%;font-family:inherit;line-height:1.15}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{display:table;box-sizing:border-box;max-width:100%;padding:0;color:inherit;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}.arco-icon{display:inline-block;width:1em;height:1em;color:inherit;font-style:normal;vertical-align:-2px;outline:none;stroke:currentColor}.arco-icon-loading,.arco-icon-spin{animation:arco-loading-circle 1s infinite cubic-bezier(0,0,1,1)}@keyframes arco-loading-circle{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.arco-icon-hover{position:relative;display:inline-block;cursor:pointer;line-height:12px}.arco-icon-hover .arco-icon{position:relative}.arco-icon-hover:before{position:absolute;display:block;box-sizing:border-box;background-color:transparent;border-radius:var(--border-radius-circle);transition:background-color .1s cubic-bezier(0,0,1,1);content:""}.arco-icon-hover:hover:before{background-color:var(--color-fill-2)}.arco-icon-hover.arco-icon-hover-disabled:before{opacity:0}.arco-icon-hover:before{top:50%;left:50%;width:20px;height:20px;transform:translate(-50%,-50%)}.arco-icon-hover-size-mini{line-height:12px}.arco-icon-hover-size-mini:before{top:50%;left:50%;width:20px;height:20px;transform:translate(-50%,-50%)}.arco-icon-hover-size-small{line-height:12px}.arco-icon-hover-size-small:before{top:50%;left:50%;width:20px;height:20px;transform:translate(-50%,-50%)}.arco-icon-hover-size-large{line-height:12px}.arco-icon-hover-size-large:before{top:50%;left:50%;width:24px;height:24px;transform:translate(-50%,-50%)}.arco-icon-hover-size-huge{line-height:12px}.arco-icon-hover-size-huge:before{top:50%;left:50%;width:24px;height:24px;transform:translate(-50%,-50%)}.fade-in-standard-enter-from,.fade-in-standard-appear-from{opacity:0}.fade-in-standard-enter-to,.fade-in-standard-appear-to{opacity:1}.fade-in-standard-enter-active,.fade-in-standard-appear-active{transition:opacity .3s cubic-bezier(.34,.69,.1,1)}.fade-in-standard-leave-from{opacity:1}.fade-in-standard-leave-to{opacity:0}.fade-in-standard-leave-active{transition:opacity .3s cubic-bezier(.34,.69,.1,1)}.fade-in-enter-from,.fade-in-appear-from{opacity:0}.fade-in-enter-to,.fade-in-appear-to{opacity:1}.fade-in-enter-active,.fade-in-appear-active{transition:opacity .1s cubic-bezier(0,0,1,1)}.fade-in-leave-from{opacity:1}.fade-in-leave-to{opacity:0}.fade-in-leave-active{transition:opacity .1s cubic-bezier(0,0,1,1)}.zoom-in-enter-from,.zoom-in-appear-from{transform:scale(.5);opacity:0}.zoom-in-enter-to,.zoom-in-appear-to{transform:scale(1);opacity:1}.zoom-in-enter-active,.zoom-in-appear-active{transition:opacity .3s cubic-bezier(.34,.69,.1,1),transform .3s cubic-bezier(.34,.69,.1,1)}.zoom-in-leave-from{transform:scale(1);opacity:1}.zoom-in-leave-to{transform:scale(.5);opacity:0}.zoom-in-leave-active{transition:opacity .3s cubic-bezier(.34,.69,.1,1),transform .3s cubic-bezier(.34,.69,.1,1)}.zoom-in-fade-out-enter-from,.zoom-in-fade-out-appear-from{transform:scale(.5);opacity:0}.zoom-in-fade-out-enter-to,.zoom-in-fade-out-appear-to{transform:scale(1);opacity:1}.zoom-in-fade-out-enter-active,.zoom-in-fade-out-appear-active{transition:opacity .3s cubic-bezier(.3,1.3,.3,1),transform .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-fade-out-leave-from{transform:scale(1);opacity:1}.zoom-in-fade-out-leave-to{transform:scale(.5);opacity:0}.zoom-in-fade-out-leave-active{transition:opacity .3s cubic-bezier(.3,1.3,.3,1),transform .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-big-enter-from,.zoom-in-big-appear-from{transform:scale(.5);opacity:0}.zoom-in-big-enter-to,.zoom-in-big-appear-to{transform:scale(1);opacity:1}.zoom-in-big-enter-active,.zoom-in-big-appear-active{transition:opacity .2s cubic-bezier(0,0,1,1),transform .2s cubic-bezier(0,0,1,1)}.zoom-in-big-leave-from{transform:scale(1);opacity:1}.zoom-in-big-leave-to{transform:scale(.2);opacity:0}.zoom-in-big-leave-active{transition:opacity .2s cubic-bezier(0,0,1,1),transform .2s cubic-bezier(0,0,1,1)}.zoom-in-left-enter-from,.zoom-in-left-appear-from{transform:scale(.1);opacity:.1}.zoom-in-left-enter-to,.zoom-in-left-appear-to{transform:scale(1);opacity:1}.zoom-in-left-enter-active,.zoom-in-left-appear-active{transform-origin:0 50%;transition:opacity .3s cubic-bezier(0,0,1,1),transform .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-left-leave-from{transform:scale(1);opacity:1}.zoom-in-left-leave-to{transform:scale(.1);opacity:.1}.zoom-in-left-leave-active{transform-origin:0 50%;transition:opacity .3s cubic-bezier(0,0,1,1),transform .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-top-enter-from,.zoom-in-top-appear-from{transform:scaleY(.8) translateZ(0);opacity:0}.zoom-in-top-enter-to,.zoom-in-top-appear-to{transform:scaleY(1) translateZ(0);opacity:1}.zoom-in-top-enter-active,.zoom-in-top-appear-active{transform-origin:0 0;transition:transform .3s cubic-bezier(.3,1.3,.3,1),opacity .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-top-leave-from{transform:scaleY(1) translateZ(0);opacity:1}.zoom-in-top-leave-to{transform:scaleY(.8) translateZ(0);opacity:0}.zoom-in-top-leave-active{transform-origin:0 0;transition:transform .3s cubic-bezier(.3,1.3,.3,1),opacity .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-bottom-enter-from,.zoom-in-bottom-appear-from{transform:scaleY(.8) translateZ(0);opacity:0}.zoom-in-bottom-enter-to,.zoom-in-bottom-appear-to{transform:scaleY(1) translateZ(0);opacity:1}.zoom-in-bottom-enter-active,.zoom-in-bottom-appear-active{transform-origin:100% 100%;transition:transform .3s cubic-bezier(.3,1.3,.3,1),opacity .3s cubic-bezier(.3,1.3,.3,1)}.zoom-in-bottom-leave-from{transform:scaleY(1) translateZ(0);opacity:1}.zoom-in-bottom-leave-to{transform:scaleY(.8) translateZ(0);opacity:0}.zoom-in-bottom-leave-active{transform-origin:100% 100%;transition:transform .3s cubic-bezier(.3,1.3,.3,1),opacity .3s cubic-bezier(.3,1.3,.3,1)}.slide-dynamic-origin-enter-from,.slide-dynamic-origin-appear-from{transform:scaleY(.9);transform-origin:0 0;opacity:0}.slide-dynamic-origin-enter-to,.slide-dynamic-origin-appear-to{transform:scaleY(1);transform-origin:0 0;opacity:1}.slide-dynamic-origin-enter-active,.slide-dynamic-origin-appear-active{transition:transform .2s cubic-bezier(.34,.69,.1,1),opacity .2s cubic-bezier(.34,.69,.1,1)}.slide-dynamic-origin-leave-from{transform:scaleY(1);transform-origin:0 0;opacity:1}.slide-dynamic-origin-leave-to{transform:scaleY(.9);transform-origin:0 0;opacity:0}.slide-dynamic-origin-leave-active{transition:transform .2s cubic-bezier(.34,.69,.1,1),opacity .2s cubic-bezier(.34,.69,.1,1)}.slide-left-enter-from,.slide-left-appear-from{transform:translate(-100%)}.slide-left-enter-to,.slide-left-appear-to{transform:translate(0)}.slide-left-enter-active,.slide-left-appear-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-left-leave-from{transform:translate(0)}.slide-left-leave-to{transform:translate(-100%)}.slide-left-leave-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-right-enter-from,.slide-right-appear-from{transform:translate(100%)}.slide-right-enter-to,.slide-right-appear-to{transform:translate(0)}.slide-right-enter-active,.slide-right-appear-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-right-leave-from{transform:translate(0)}.slide-right-leave-to{transform:translate(100%)}.slide-right-leave-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-top-enter-from,.slide-top-appear-from{transform:translateY(-100%)}.slide-top-enter-to,.slide-top-appear-to{transform:translateY(0)}.slide-top-enter-active,.slide-top-appear-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-top-leave-from{transform:translateY(0)}.slide-top-leave-to{transform:translateY(-100%)}.slide-top-leave-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-bottom-enter-from,.slide-bottom-appear-from{transform:translateY(100%)}.slide-bottom-enter-to,.slide-bottom-appear-to{transform:translateY(0)}.slide-bottom-enter-active,.slide-bottom-appear-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}.slide-bottom-leave-from{transform:translateY(0)}.slide-bottom-leave-to{transform:translateY(100%)}.slide-bottom-leave-active{transition:transform .3s cubic-bezier(.34,.69,.1,1)}body{--red-1: 255,236,232;--red-2: 253,205,197;--red-3: 251,172,163;--red-4: 249,137,129;--red-5: 247,101,96;--red-6: 245,63,63;--red-7: 203,39,45;--red-8: 161,21,30;--red-9: 119,8,19;--red-10: 77,0,10;--orangered-1: 255,243,232;--orangered-2: 253,221,195;--orangered-3: 252,197,159;--orangered-4: 250,172,123;--orangered-5: 249,144,87;--orangered-6: 247,114,52;--orangered-7: 204,81,32;--orangered-8: 162,53,17;--orangered-9: 119,31,6;--orangered-10: 77,14,0;--orange-1: 255,247,232;--orange-2: 255,228,186;--orange-3: 255,207,139;--orange-4: 255,182,93;--orange-5: 255,154,46;--orange-6: 255,125,0;--orange-7: 210,95,0;--orange-8: 166,69,0;--orange-9: 121,46,0;--orange-10: 77,27,0;--gold-1: 255,252,232;--gold-2: 253,244,191;--gold-3: 252,233,150;--gold-4: 250,220,109;--gold-5: 249,204,69;--gold-6: 247,186,30;--gold-7: 204,146,19;--gold-8: 162,109,10;--gold-9: 119,75,4;--gold-10: 77,45,0;--yellow-1: 254,255,232;--yellow-2: 254,254,190;--yellow-3: 253,250,148;--yellow-4: 252,242,107;--yellow-5: 251,232,66;--yellow-6: 250,220,25;--yellow-7: 207,175,15;--yellow-8: 163,132,8;--yellow-9: 120,93,3;--yellow-10: 77,56,0;--lime-1: 252,255,232;--lime-2: 237,248,187;--lime-3: 220,241,144;--lime-4: 201,233,104;--lime-5: 181,226,65;--lime-6: 159,219,29;--lime-7: 126,183,18;--lime-8: 95,148,10;--lime-9: 67,112,4;--lime-10: 42,77,0;--green-1: 232,255,234;--green-2: 175,240,181;--green-3: 123,225,136;--green-4: 76,210,99;--green-5: 35,195,67;--green-6: 0,180,42;--green-7: 0,154,41;--green-8: 0,128,38;--green-9: 0,102,34;--green-10: 0,77,28;--cyan-1: 232,255,251;--cyan-2: 183,244,236;--cyan-3: 137,233,224;--cyan-4: 94,223,214;--cyan-5: 55,212,207;--cyan-6: 20,201,201;--cyan-7: 13,165,170;--cyan-8: 7,130,139;--cyan-9: 3,97,108;--cyan-10: 0,66,77;--blue-1: 232,247,255;--blue-2: 195,231,254;--blue-3: 159,212,253;--blue-4: 123,192,252;--blue-5: 87,169,251;--blue-6: 52,145,250;--blue-7: 32,108,207;--blue-8: 17,75,163;--blue-9: 6,48,120;--blue-10: 0,26,77;--arcoblue-1: 232,243,255;--arcoblue-2: 190,218,255;--arcoblue-3: 148,191,255;--arcoblue-4: 106,161,255;--arcoblue-5: 64,128,255;--arcoblue-6: 22,93,255;--arcoblue-7: 14,66,210;--arcoblue-8: 7,44,166;--arcoblue-9: 3,26,121;--arcoblue-10: 0,13,77;--purple-1: 245,232,255;--purple-2: 221,190,246;--purple-3: 195,150,237;--purple-4: 168,113,227;--purple-5: 141,78,218;--purple-6: 114,46,209;--purple-7: 85,29,176;--purple-8: 60,16,143;--purple-9: 39,6,110;--purple-10: 22,0,77;--pinkpurple-1: 255,232,251;--pinkpurple-2: 247,186,239;--pinkpurple-3: 240,142,230;--pinkpurple-4: 232,101,223;--pinkpurple-5: 225,62,219;--pinkpurple-6: 217,26,217;--pinkpurple-7: 176,16,182;--pinkpurple-8: 138,9,147;--pinkpurple-9: 101,3,112;--pinkpurple-10: 66,0,77;--magenta-1: 255,232,241;--magenta-2: 253,194,219;--magenta-3: 251,157,199;--magenta-4: 249,121,183;--magenta-5: 247,84,168;--magenta-6: 245,49,157;--magenta-7: 203,30,131;--magenta-8: 161,16,105;--magenta-9: 119,6,79;--magenta-10: 77,0,52;--gray-1: 247,248,250;--gray-2: 242,243,245;--gray-3: 229,230,235;--gray-4: 201,205,212;--gray-5: 169,174,184;--gray-6: 134,144,156;--gray-7: 107,119,133;--gray-8: 78,89,105;--gray-9: 39,46,59;--gray-10: 29,33,41;--success-1: var(--green-1);--success-2: var(--green-2);--success-3: var(--green-3);--success-4: var(--green-4);--success-5: var(--green-5);--success-6: var(--green-6);--success-7: var(--green-7);--success-8: var(--green-8);--success-9: var(--green-9);--success-10: var(--green-10);--primary-1: var(--arcoblue-1);--primary-2: var(--arcoblue-2);--primary-3: var(--arcoblue-3);--primary-4: var(--arcoblue-4);--primary-5: var(--arcoblue-5);--primary-6: var(--arcoblue-6);--primary-7: var(--arcoblue-7);--primary-8: var(--arcoblue-8);--primary-9: var(--arcoblue-9);--primary-10: var(--arcoblue-10);--danger-1: var(--red-1);--danger-2: var(--red-2);--danger-3: var(--red-3);--danger-4: var(--red-4);--danger-5: var(--red-5);--danger-6: var(--red-6);--danger-7: var(--red-7);--danger-8: var(--red-8);--danger-9: var(--red-9);--danger-10: var(--red-10);--warning-1: var(--orange-1);--warning-2: var(--orange-2);--warning-3: var(--orange-3);--warning-4: var(--orange-4);--warning-5: var(--orange-5);--warning-6: var(--orange-6);--warning-7: var(--orange-7);--warning-8: var(--orange-8);--warning-9: var(--orange-9);--warning-10: var(--orange-10);--link-1: var(--arcoblue-1);--link-2: var(--arcoblue-2);--link-3: var(--arcoblue-3);--link-4: var(--arcoblue-4);--link-5: var(--arcoblue-5);--link-6: var(--arcoblue-6);--link-7: var(--arcoblue-7);--link-8: var(--arcoblue-8);--link-9: var(--arcoblue-9);--link-10: var(--arcoblue-10)}body[arco-theme=dark]{--red-1: 77,0,10;--red-2: 119,6,17;--red-3: 161,22,31;--red-4: 203,46,52;--red-5: 245,78,78;--red-6: 247,105,101;--red-7: 249,141,134;--red-8: 251,176,167;--red-9: 253,209,202;--red-10: 255,240,236;--orangered-1: 77,14,0;--orangered-2: 119,30,5;--orangered-3: 162,55,20;--orangered-4: 204,87,41;--orangered-5: 247,126,69;--orangered-6: 249,146,90;--orangered-7: 250,173,125;--orangered-8: 252,198,161;--orangered-9: 253,222,197;--orangered-10: 255,244,235;--orange-1: 77,27,0;--orange-2: 121,48,4;--orange-3: 166,75,10;--orange-4: 210,105,19;--orange-5: 255,141,31;--orange-6: 255,150,38;--orange-7: 255,179,87;--orange-8: 255,205,135;--orange-9: 255,227,184;--orange-10: 255,247,232;--gold-1: 77,45,0;--gold-2: 119,75,4;--gold-3: 162,111,15;--gold-4: 204,150,31;--gold-5: 247,192,52;--gold-6: 249,204,68;--gold-7: 250,220,108;--gold-8: 252,233,149;--gold-9: 253,244,190;--gold-10: 255,252,232;--yellow-1: 77,56,0;--yellow-2: 120,94,7;--yellow-3: 163,134,20;--yellow-4: 207,179,37;--yellow-5: 250,225,60;--yellow-6: 251,233,75;--yellow-7: 252,243,116;--yellow-8: 253,250,157;--yellow-9: 254,254,198;--yellow-10: 254,255,240;--lime-1: 42,77,0;--lime-2: 68,112,6;--lime-3: 98,148,18;--lime-4: 132,183,35;--lime-5: 168,219,57;--lime-6: 184,226,75;--lime-7: 203,233,112;--lime-8: 222,241,152;--lime-9: 238,248,194;--lime-10: 253,255,238;--green-1: 0,77,28;--green-2: 4,102,37;--green-3: 10,128,45;--green-4: 18,154,55;--green-5: 29,180,64;--green-6: 39,195,70;--green-7: 80,210,102;--green-8: 126,225,139;--green-9: 178,240,183;--green-10: 235,255,236;--cyan-1: 0,66,77;--cyan-2: 6,97,108;--cyan-3: 17,131,139;--cyan-4: 31,166,170;--cyan-5: 48,201,201;--cyan-6: 63,212,207;--cyan-7: 102,223,215;--cyan-8: 144,233,225;--cyan-9: 190,244,237;--cyan-10: 240,255,252;--blue-1: 0,26,77;--blue-2: 5,47,120;--blue-3: 19,76,163;--blue-4: 41,113,207;--blue-5: 70,154,250;--blue-6: 90,170,251;--blue-7: 125,193,252;--blue-8: 161,213,253;--blue-9: 198,232,254;--blue-10: 234,248,255;--arcoblue-1: 0,13,77;--arcoblue-2: 4,27,121;--arcoblue-3: 14,50,166;--arcoblue-4: 29,77,210;--arcoblue-5: 48,111,255;--arcoblue-6: 60,126,255;--arcoblue-7: 104,159,255;--arcoblue-8: 147,190,255;--arcoblue-9: 190,218,255;--arcoblue-10: 234,244,255;--purple-1: 22,0,77;--purple-2: 39,6,110;--purple-3: 62,19,143;--purple-4: 90,37,176;--purple-5: 123,61,209;--purple-6: 142,81,218;--purple-7: 169,116,227;--purple-8: 197,154,237;--purple-9: 223,194,246;--purple-10: 247,237,255;--pinkpurple-1: 66,0,77;--pinkpurple-2: 101,3,112;--pinkpurple-3: 138,13,147;--pinkpurple-4: 176,27,182;--pinkpurple-5: 217,46,217;--pinkpurple-6: 225,61,219;--pinkpurple-7: 232,102,223;--pinkpurple-8: 240,146,230;--pinkpurple-9: 247,193,240;--pinkpurple-10: 255,242,253;--magenta-1: 77,0,52;--magenta-2: 119,8,80;--magenta-3: 161,23,108;--magenta-4: 203,43,136;--magenta-5: 245,69,166;--magenta-6: 247,86,169;--magenta-7: 249,122,184;--magenta-8: 251,158,200;--magenta-9: 253,195,219;--magenta-10: 255,232,241;--gray-1: 23,23,26;--gray-2: 46,46,48;--gray-3: 72,72,73;--gray-4: 95,95,96;--gray-5: 120,120,122;--gray-6: 146,146,147;--gray-7: 171,171,172;--gray-8: 197,197,197;--gray-9: 223,223,223;--gray-10: 246,246,246;--primary-1: var(--arcoblue-1);--primary-2: var(--arcoblue-2);--primary-3: var(--arcoblue-3);--primary-4: var(--arcoblue-4);--primary-5: var(--arcoblue-5);--primary-6: var(--arcoblue-6);--primary-7: var(--arcoblue-7);--primary-8: var(--arcoblue-8);--primary-9: var(--arcoblue-9);--primary-10: var(--arcoblue-10);--success-1: var(--green-1);--success-2: var(--green-2);--success-3: var(--green-3);--success-4: var(--green-4);--success-5: var(--green-5);--success-6: var(--green-6);--success-7: var(--green-7);--success-8: var(--green-8);--success-9: var(--green-9);--success-10: var(--green-10);--danger-1: var(--red-1);--danger-2: var(--red-2);--danger-3: var(--red-3);--danger-4: var(--red-4);--danger-5: var(--red-5);--danger-6: var(--red-6);--danger-7: var(--red-7);--danger-8: var(--red-8);--danger-9: var(--red-9);--danger-10: var(--red-10);--warning-1: var(--orange-1);--warning-2: var(--orange-2);--warning-3: var(--orange-3);--warning-4: var(--orange-4);--warning-5: var(--orange-5);--warning-6: var(--orange-6);--warning-7: var(--orange-7);--warning-8: var(--orange-8);--warning-9: var(--orange-9);--warning-10: var(--orange-10);--link-1: var(--arcoblue-1);--link-2: var(--arcoblue-2);--link-3: var(--arcoblue-3);--link-4: var(--arcoblue-4);--link-5: var(--arcoblue-5);--link-6: var(--arcoblue-6);--link-7: var(--arcoblue-7);--link-8: var(--arcoblue-8);--link-9: var(--arcoblue-9);--link-10: var(--arcoblue-10)}body{--color-white: #ffffff;--color-black: #000000;--color-border: rgb(var(--gray-3));--color-bg-popup: var(--color-bg-5);--color-bg-1: #fff;--color-bg-2: #fff;--color-bg-3: #fff;--color-bg-4: #fff;--color-bg-5: #fff;--color-bg-white: #fff;--color-neutral-1: rgb(var(--gray-1));--color-neutral-2: rgb(var(--gray-2));--color-neutral-3: rgb(var(--gray-3));--color-neutral-4: rgb(var(--gray-4));--color-neutral-5: rgb(var(--gray-5));--color-neutral-6: rgb(var(--gray-6));--color-neutral-7: rgb(var(--gray-7));--color-neutral-8: rgb(var(--gray-8));--color-neutral-9: rgb(var(--gray-9));--color-neutral-10: rgb(var(--gray-10));--color-text-1: var(--color-neutral-10);--color-text-2: var(--color-neutral-8);--color-text-3: var(--color-neutral-6);--color-text-4: var(--color-neutral-4);--color-border-1: var(--color-neutral-2);--color-border-2: var(--color-neutral-3);--color-border-3: var(--color-neutral-4);--color-border-4: var(--color-neutral-6);--color-fill-1: var(--color-neutral-1);--color-fill-2: var(--color-neutral-2);--color-fill-3: var(--color-neutral-3);--color-fill-4: var(--color-neutral-4);--color-primary-light-1: rgb(var(--primary-1));--color-primary-light-2: rgb(var(--primary-2));--color-primary-light-3: rgb(var(--primary-3));--color-primary-light-4: rgb(var(--primary-4));--color-link-light-1: rgb(var(--link-1));--color-link-light-2: rgb(var(--link-2));--color-link-light-3: rgb(var(--link-3));--color-link-light-4: rgb(var(--link-4));--color-secondary: var(--color-neutral-2);--color-secondary-hover: var(--color-neutral-3);--color-secondary-active: var(--color-neutral-4);--color-secondary-disabled: var(--color-neutral-1);--color-danger-light-1: rgb(var(--danger-1));--color-danger-light-2: rgb(var(--danger-2));--color-danger-light-3: rgb(var(--danger-3));--color-danger-light-4: rgb(var(--danger-4));--color-success-light-1: rgb(var(--success-1));--color-success-light-2: rgb(var(--success-2));--color-success-light-3: rgb(var(--success-3));--color-success-light-4: rgb(var(--success-4));--color-warning-light-1: rgb(var(--warning-1));--color-warning-light-2: rgb(var(--warning-2));--color-warning-light-3: rgb(var(--warning-3));--color-warning-light-4: rgb(var(--warning-4));--border-radius-none: 0;--border-radius-small: 2px;--border-radius-medium: 4px;--border-radius-large: 8px;--border-radius-circle: 50%;--color-tooltip-bg: rgb(var(--gray-10));--color-spin-layer-bg: rgba(255, 255, 255, .6);--color-menu-dark-bg: #232324;--color-menu-light-bg: #ffffff;--color-menu-dark-hover: rgba(255, 255, 255, .04);--color-mask-bg: rgba(29, 33, 41, .6)}body[arco-theme=dark]{--color-white: rgba(255, 255, 255, .9);--color-black: #000000;--color-border: #333335;--color-bg-1: #17171a;--color-bg-2: #232324;--color-bg-3: #2a2a2b;--color-bg-4: #313132;--color-bg-5: #373739;--color-bg-white: #f6f6f6;--color-text-1: rgba(255, 255, 255, .9);--color-text-2: rgba(255, 255, 255, .7);--color-text-3: rgba(255, 255, 255, .5);--color-text-4: rgba(255, 255, 255, .3);--color-fill-1: rgba(255, 255, 255, .04);--color-fill-2: rgba(255, 255, 255, .08);--color-fill-3: rgba(255, 255, 255, .12);--color-fill-4: rgba(255, 255, 255, .16);--color-primary-light-1: rgba(var(--primary-6), .2);--color-primary-light-2: rgba(var(--primary-6), .35);--color-primary-light-3: rgba(var(--primary-6), .5);--color-primary-light-4: rgba(var(--primary-6), .65);--color-secondary: rgba(var(--gray-9), .08);--color-secondary-hover: rgba(var(--gray-8), .16);--color-secondary-active: rgba(var(--gray-7), .24);--color-secondary-disabled: rgba(var(--gray-9), .08);--color-danger-light-1: rgba(var(--danger-6), .2);--color-danger-light-2: rgba(var(--danger-6), .35);--color-danger-light-3: rgba(var(--danger-6), .5);--color-danger-light-4: rgba(var(--danger-6), .65);--color-success-light-1: rgb(var(--success-6), .2);--color-success-light-2: rgb(var(--success-6), .35);--color-success-light-3: rgb(var(--success-6), .5);--color-success-light-4: rgb(var(--success-6), .65);--color-warning-light-1: rgb(var(--warning-6), .2);--color-warning-light-2: rgb(var(--warning-6), .35);--color-warning-light-3: rgb(var(--warning-6), .5);--color-warning-light-4: rgb(var(--warning-6), .65);--color-link-light-1: rgb(var(--link-6), .2);--color-link-light-2: rgb(var(--link-6), .35);--color-link-light-3: rgb(var(--link-6), .5);--color-link-light-4: rgb(var(--link-6), .65);--color-tooltip-bg: #373739;--color-spin-layer-bg: rgba(51, 51, 51, .6);--color-menu-dark-bg: #232324;--color-menu-light-bg: #232324;--color-menu-dark-hover: var(--color-fill-2);--color-mask-bg: rgba(23, 23, 26, .6)}body{font-size:14px;font-family:Inter,-apple-system,BlinkMacSystemFont,PingFang SC,Hiragino Sans GB,noto sans,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif}.arco-message-list{position:fixed;z-index:1003;display:flex;flex-direction:column;align-items:center;box-sizing:border-box;width:100%;margin:0;padding:0 10px;text-align:center;pointer-events:none}.arco-message-list-top{top:40px}.arco-message-list-bottom{bottom:40px}.arco-message{position:relative;display:inline-flex;align-items:center;margin-bottom:16px;padding:10px 16px;overflow:hidden;line-height:1;text-align:center;list-style:none;background-color:var(--color-bg-popup);border:1px solid var(--color-neutral-3);border-radius:var(--border-radius-small);box-shadow:0 4px 10px #0000001a;transition:all .1s cubic-bezier(0,0,1,1);pointer-events:auto}.arco-message-icon{display:inline-block;margin-right:8px;color:var(--color-text-1);font-size:20px;vertical-align:middle;animation:arco-msg-fade .1s cubic-bezier(0,0,1,1),arco-msg-fade .4s cubic-bezier(.3,1.3,.3,1)}.arco-message-content{font-size:14px;color:var(--color-text-1);vertical-align:middle}.arco-message-info{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-info .arco-message-icon{color:rgb(var(--primary-6))}.arco-message-info .arco-message-content{color:var(--color-text-1)}.arco-message-success{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-success .arco-message-icon{color:rgb(var(--success-6))}.arco-message-success .arco-message-content{color:var(--color-text-1)}.arco-message-warning{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-warning .arco-message-icon{color:rgb(var(--warning-6))}.arco-message-warning .arco-message-content{color:var(--color-text-1)}.arco-message-error{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-error .arco-message-icon{color:rgb(var(--danger-6))}.arco-message-error .arco-message-content{color:var(--color-text-1)}.arco-message-loading{background-color:var(--color-bg-popup);border-color:var(--color-neutral-3)}.arco-message-loading .arco-message-icon{color:rgb(var(--primary-6))}.arco-message-loading .arco-message-content{color:var(--color-text-1)}.arco-message-close-btn{margin-left:8px;color:var(--color-text-1);font-size:12px}.arco-message .arco-icon-hover.arco-message-icon-hover:before{width:20px;height:20px}.fade-message-enter-from,.fade-message-appear-from{opacity:0}.fade-message-enter-to,.fade-message-appear-to{opacity:1}.fade-message-enter-active,.fade-message-appear-active{transition:opacity .1s cubic-bezier(0,0,1,1)}.fade-message-leave-from{opacity:1}.fade-message-leave-to{opacity:0}.fade-message-leave-active{position:absolute}.flip-list-move{transition:transform .8s ease}@keyframes arco-msg-fade{0%{opacity:0}to{opacity:1}}@keyframes arco-msg-scale{0%{transform:scale(0)}to{transform:scale(1)}}:root{--c-brand: #3eaf7c;--c-brand-light: #4abf8a;--c-bg: #ffffff;--c-bg-light: #f3f4f5;--c-bg-lighter: #eeeeee;--c-bg-navbar: var(--c-bg);--c-bg-sidebar: var(--c-bg);--c-bg-arrow: #cccccc;--c-text: #2c3e50;--c-text-accent: var(--c-brand);--c-text-light: #3a5169;--c-text-lighter: #4e6e8e;--c-text-lightest: #6a8bad;--c-text-quote: #999999;--c-border: #eaecef;--c-border-dark: #dfe2e5;--c-tip: #42b983;--c-tip-bg: var(--c-bg-light);--c-tip-title: var(--c-text);--c-tip-text: var(--c-text);--c-tip-text-accent: var(--c-text-accent);--c-warning: #e7c000;--c-warning-bg: #fffae3;--c-warning-title: #ad9000;--c-warning-text: #746000;--c-warning-text-accent: var(--c-text);--c-danger: #cc0000;--c-danger-bg: #ffe0e0;--c-danger-title: #990000;--c-danger-text: #660000;--c-danger-text-accent: var(--c-text);--c-details-bg: #eeeeee;--c-badge-tip: var(--c-tip);--c-badge-warning: var(--c-warning);--c-badge-danger: var(--c-danger);--t-color: .3s ease;--t-transform: .3s ease;--code-bg-color: #282c34;--code-hl-bg-color: rgba(0, 0, 0, .66);--code-ln-color: #9e9e9e;--code-ln-wrapper-width: 3.5rem;--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;--font-family-code: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;--navbar-height: 3.6rem;--navbar-padding-v: .7rem;--navbar-padding-h: 1.5rem;--sidebar-width: 20rem;--sidebar-width-mobile: calc(var(--sidebar-width) * .82);--content-width: 740px;--homepage-width: 960px}html.dark{--c-brand: #3aa675;--c-brand-light: #349469;--c-bg: #22272e;--c-bg-light: #2b313a;--c-bg-lighter: #262c34;--c-text: #adbac7;--c-text-light: #96a7b7;--c-text-lighter: #8b9eb0;--c-text-lightest: #8094a8;--c-border: #3e4c5a;--c-border-dark: #34404c;--c-tip: #318a62;--c-warning: #ceab00;--c-warning-bg: #7e755b;--c-warning-title: #ceac03;--c-warning-text: #362e00;--c-danger: #940000;--c-danger-bg: #806161;--c-danger-title: #610000;--c-danger-text: #3a0000;--c-details-bg: #323843;--code-hl-bg-color: #363b46}@font-face{font-family:octicons-link;src:url(data:font/woff;charset=utf-8;base64,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) format("woff")}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;color:var(--c-text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol;font-size:14px;line-height:1.5;word-wrap:break-word;transition:background-color var(--t-color),border-color var(--t-color)}.g-emoji{display:inline-block;min-width:1ch;font-family:"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,serif;font-size:1em;font-style:normal!important;font-weight:400;line-height:1;vertical-align:-.075em}.markdown-body .pl-c{color:#6a737d}.markdown-body .pl-c1,.markdown-body .pl-s .pl-v{color:#005cc5}.markdown-body .pl-e,.markdown-body .pl-en{color:#6f42c1}.markdown-body .pl-smi,.markdown-body .pl-s .pl-s1{color:var(--c-text)}.markdown-body .pl-ent{color:#22863a}.markdown-body .pl-k{color:#d73a49}.markdown-body .pl-s,.markdown-body .pl-pds,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sre,.markdown-body .pl-sr .pl-sra{color:var(--c-text-lighter)}.markdown-body .pl-v,.markdown-body .pl-smw{color:#e36209}.markdown-body .pl-bu{color:#b31d28}.markdown-body .pl-ii{color:#fafbfc;background-color:#b31d28}.markdown-body .pl-c2{color:#fafbfc;background-color:#d73a49}.markdown-body .pl-c2:before{content:"^M"}.markdown-body .pl-sr .pl-cce{font-weight:700;color:#22863a}.markdown-body .pl-ml{color:#735c0f}.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms{font-weight:700;color:#005cc5}.markdown-body .pl-mi{font-style:italic;color:#24292e}.markdown-body .pl-mb{font-weight:700;color:#24292e}.markdown-body .pl-md{color:#b31d28;background-color:#ffeef0}.markdown-body .pl-mi1{color:#22863a;background-color:#f0fff4}.markdown-body .pl-mc{color:#e36209;background-color:#ffebda}.markdown-body .pl-mi2{color:#f6f8fa;background-color:#005cc5}.markdown-body .pl-mdr{font-weight:700;color:#6f42c1}.markdown-body .pl-ba{color:#586069}.markdown-body .pl-sg{color:#959da5}.markdown-body .pl-corl{text-decoration:underline;color:var(--c-text-lighter)}.markdown-body .octicon{display:inline-block;vertical-align:text-top;fill:currentColor}.markdown-body a{background-color:transparent;-webkit-text-decoration-skip:objects}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:inherit}.markdown-body strong{font-weight:bolder}.markdown-body h1{font-size:2em;margin:.67em 0}.markdown-body img{border-style:none}.markdown-body svg:not(:root){overflow:hidden}.markdown-body code,.markdown-body kbd,.markdown-body pre{font-family:monospace,monospace;font-size:1em}.markdown-body hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}.markdown-body input{font:inherit;margin:0}.markdown-body input{overflow:visible}.markdown-body [type=checkbox]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}.markdown-body *{-webkit-box-sizing:border-box;box-sizing:border-box}.markdown-body input{font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body a{color:#0366d6;text-decoration:none}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border:0;border-bottom:1px solid #dfe2e5}.markdown-body hr:before{display:table;content:""}.markdown-body hr:after{display:table;clear:both;content:""}.markdown-body table{border-spacing:0;border-collapse:collapse}.markdown-body td,.markdown-body th{padding:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:0;margin-bottom:0}.markdown-body h1{font-size:32px;font-weight:600}.markdown-body h2{font-size:24px;font-weight:600}.markdown-body h3{font-size:20px;font-weight:600}.markdown-body h4,.markdown-body h5{font-size:14px;font-weight:600}.markdown-body h6{font-size:12px;font-weight:600}.markdown-body p{margin-top:0;margin-bottom:10px}.markdown-body blockquote{margin:0}.markdown-body ul,.markdown-body ol{padding-left:0;margin-top:0;margin-bottom:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ul ul ol,.markdown-body ul ol ol,.markdown-body ol ul ol,.markdown-body ol ol ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body code{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:12px}.markdown-body pre{margin-top:0;margin-bottom:0;font:12px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}.markdown-body .octicon{vertical-align:text-bottom}.markdown-body .pl-0{padding-left:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .pl-3{padding-left:14px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body:before{display:table;content:""}.markdown-body:after{display:table;clear:both;content:""}.markdown-body>*:first-child{margin-top:0!important}.markdown-body>*:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:none}.markdown-body p,.markdown-body blockquote,.markdown-body ul,.markdown-body ol,.markdown-body dl,.markdown-body table,.markdown-body pre{margin-top:0;margin-bottom:14px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid var(--c-border)}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:solid 1px #c6cbd1;border-bottom-color:#959da5;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 #959da5;box-shadow:inset 0 -1px #959da5}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:14px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1{padding-bottom:.3em;font-size:2em;border-bottom:1px solid #eaecef}.markdown-body h2{padding-bottom:.3em;font-size:1.5em;border-bottom:1px solid #eaecef}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body ul,.markdown-body ol{padding-left:2em}.markdown-body ul ul,.markdown-body ul ol,.markdown-body ol ol,.markdown-body ol ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:14px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:14px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 14px;margin-bottom:14px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table th,.markdown-body table td{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;-webkit-box-sizing:content-box;box-sizing:content-box;background-color:#fff}.markdown-body code{padding:.2em 0;margin:0;font-size:85%;border-radius:3px}.markdown-body code:before,.markdown-body code:after{letter-spacing:-.2em;content:" "}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:14px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:14px;overflow:auto;font-size:85%;line-height:1.45;background-color:var(--c-tip-bg);border-radius:3px;color:var(--c-text);transition:background-color var(--t-color),border-color var(--t-color)}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0;color:var(--c-text)}.markdown-body pre code:before,.markdown-body pre code:after{content:normal}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:solid 1px #d1d5da;border-bottom-color:#c6cbd1;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 #c6cbd1;box-shadow:inset 0 -1px #c6cbd1}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle}.markdown-body hr{border-bottom-color:#eee}.gt-container{-webkit-box-sizing:border-box;box-sizing:border-box;font-size:14px}.gt-container *{-webkit-box-sizing:border-box;box-sizing:border-box}.gt-container a{color:var(--c-text-accent);transition:background-color var(--t-color),border-color var(--t-color)}.gt-container a.is--active{color:var(--c-text);cursor:default!important}.gt-container a.is--active:hover{color:var(--c-text-accent)}.gt-container .hide{display:none!important}.gt-container .gt-svg{display:inline-block;width:1em;height:1em;vertical-align:sub}.gt-container .gt-ico-arrdown{fill:var(--c-text)}.gt-container .gt-svg svg{width:100%;height:100%;fill:var(--c-text-accent)}.gt-container .gt-ico{display:inline-block}.gt-container .gt-ico-text{margin-left:.3125em}.gt-container .gt-ico-tip{font-size:.875em}.gt-container .gt-ico-github,.gt-container .gt-ico-github .gt-svg{width:100%;height:100%}.gt-container .gt-ico-github svg{fill:var(--c-text)}.gt-container .gt-spinner{position:relative}.gt-container .gt-spinner:before{content:"";-webkit-box-sizing:border-box;box-sizing:border-box;position:absolute;top:3px;width:.75em;height:.75em;margin-top:-.1875em;margin-left:-.375em;border-radius:50%;border:1px solid #fff;border-top-color:var(--c-text-accent);-webkit-animation:gt-kf-rotate .6s linear infinite;animation:gt-kf-rotate .6s linear infinite}.gt-container .gt-loader{position:relative;border:1px solid #999;-webkit-animation:ease gt-kf-rotate 1.5s infinite;animation:ease gt-kf-rotate 1.5s infinite;display:inline-block;font-style:normal;width:1.75em;height:1.75em;line-height:1.75em;border-radius:50%}.gt-container .gt-loader:before{content:"";position:absolute;display:block;top:0;left:50%;margin-top:-.1875em;margin-left:-.1875em;width:.375em;height:.375em;background-color:#999;border-radius:50%}.gt-container .gt-avatar{display:inline-block;width:3.125em;height:3.125em}@media (max-width: 479px){.gt-container .gt-avatar{width:2em;height:2em}}.gt-container .gt-avatar img{width:100%;height:auto;border-radius:3px}.gt-container .gt-avatar-github{width:3.125em;height:3.125em;cursor:pointer}@media (max-width: 479px){.gt-container .gt-avatar-github{width:2em;height:2em}}.gt-container .gt-btn{padding:.75em .95em;display:inline-block;line-height:1;text-decoration:none;white-space:nowrap;cursor:pointer;border:1px solid var(--c-text-accent);border-radius:5px;background-color:var(--c-brand);color:#fff;outline:none;font-size:.75em;transition:background-color var(--t-color),border-color var(--t-color)}.gt-container .gt-btn-text{font-weight:400}.gt-header-controls .gt-btn-public .gt-btn-text{color:var(--c-bg)}.gt-container .gt-btn-loading{position:relative;margin-left:.5em;display:inline-block;width:.75em;height:1em;vertical-align:top}.gt-container .gt-btn.is--disable{cursor:not-allowed;opacity:.5}.gt-container .gt-btn-login{margin-right:0;color:var(--c-bg)}.gt-container .gt-btn-login:hover{background-color:var(--c-brand-light);border-color:var(--c-brand)}.gt-container .gt-btn-preview{background-color:var(--c-bg);color:var(--c-brand);border-color:var(--c-brand);transition:background-color var(--t-color),border-color var(--t-color)}.gt-container .gt-btn-preview:hover{color:var(--c-bg);background-color:var(--c-brand-light)}.gt-container .gt-btn-public:hover,.gt-container .gt-btn-loadmore:hover{background-color:var(--c-brand-light);border-color:var(--c-brand)}.gt-container .gt-btn-loadmore{color:var(--c-bg)}.gt-container .gt-error{text-align:center;margin:.625em;color:#ff3860}.gt-container .gt-initing{padding:1.25em 0;text-align:center}.gt-container .gt-initing-text{margin:.625em auto;font-size:92%}.gt-container .gt-no-init{padding:1.25em 0;text-align:center}.gt-container .gt-link{border-bottom:1px dotted var(--c-text-accent)}.gt-container .gt-link-counts,.gt-container .gt-link-project{text-decoration:none}.gt-container .gt-meta{margin:1.25em 0;padding:1em 0;position:relative;border-bottom:1px solid var(--c-border);font-size:1em;transition:background-color var(--t-color),border-color var(--t-color)}.gt-container .gt-meta:before,.gt-container .gt-meta:after{content:" ";display:table}.gt-container .gt-meta:after{clear:both}.gt-container .gt-counts{margin:0 .625em 0 0}.gt-container .gt-user{float:right;margin:0;font-size:92%}.gt-container .gt-user-pic{width:14px;height:14px;vertical-align:top;margin-right:.5em}.gt-container .gt-user-inner{display:inline-block;cursor:pointer}.gt-container .gt-user .gt-ico{margin:0 0 0 .3125em}.gt-container .gt-user .gt-ico svg{fill:inherit}.gt-container .gt-user .is--poping .gt-ico svg{fill:var(--c-text-accent)}.gt-container .gt-version{color:#a1a1a1;margin-left:.375em}.gt-container .gt-copyright{margin:0 .9375em .5em;border-top:1px solid var(--c-border);padding-top:.5em}.gt-container .gt-popup{position:absolute;right:0;top:2.375em;background-color:var(--c-bg-navbar);display:block!important;border:1px solid var(--c-border);padding:.625em 0;font-size:.875em;letter-spacing:.5px;box-sizing:border-box;z-index:10}.gt-container .gt-popup .gt-action{cursor:pointer;display:block;margin:.5em 0;padding:0 1.125em;position:relative;text-decoration:none}.gt-container .gt-popup .gt-action.is--active:before{content:"";width:.25em;height:.25em;background:var(--c-text-accent);position:absolute;left:.5em;top:.4375em}.gt-container .gt-header{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex}.gt-container .gt-header-comment{-webkit-box-flex:1;-ms-flex:1;flex:1;padding-left:1.25em;width:90%}@media (max-width: 479px){.gt-container .gt-header-comment{padding-left:.875em}}.gt-container .gt-header-textarea{padding:.75em;display:block;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;min-height:5.125em;max-height:15em;border-radius:5px;border:1px solid var(--c-border);font-size:.875em;word-wrap:break-word;resize:vertical;background-color:var(--c-bg);outline:none;-webkit-transition:all .25s ease;transition:background-color var(--t-color),border-color var(--t-color)}.gt-header-textarea{color:var(--c-text)}.gt-container .gt-header-preview{padding:.75em;border-radius:5px;border:1px solid var(--c-border);background-color:var(--c-bg)}.gt-container .gt-header-controls{position:relative;margin:.75em 0 0}.gt-container .gt-header-controls:before,.gt-container .gt-header-controls:after{content:" ";display:table}.gt-container .gt-header-controls:after{clear:both}@media (max-width: 479px){.gt-container .gt-header-controls{margin:0}}.gt-container .gt-header-controls-tip{font-size:13px;color:var(--c-text-accent);text-decoration:none;vertical-align:sub}@media (max-width: 479px){.gt-container .gt-header-controls-tip{display:none}}.gt-container .gt-header-controls .gt-btn{float:right;margin-left:1.2em}@media (max-width: 479px){.gt-container .gt-header-controls .gt-btn{float:none;width:100%;margin:.75em 0 0}}.gt-container:after{content:"";position:fixed;bottom:100%;left:0;right:0;top:0;opacity:0}.gt-container.gt-input-focused{position:relative}.gt-container.gt-input-focused:after{content:"";position:fixed;bottom:0%;left:0;right:0;top:0;background:#000;opacity:.6;-webkit-transition:opacity .3s,bottom 0s;transition:opacity .3s,bottom 0s;z-index:9999}.gt-container.gt-input-focused .gt-header-comment{z-index:10000}.gt-container .gt-comments{padding-top:1.25em}.gt-container .gt-comments-null{text-align:center}.gt-container .gt-comments-controls{margin:1.25em 0;text-align:center}.gt-container .gt-comment{position:relative;padding:.625em 0;display:-webkit-box;display:-ms-flexbox;display:flex}.gt-container .gt-comment-content{-webkit-box-flex:1;-ms-flex:1;flex:1;margin-left:1.25em;padding:.75em 1em;background-color:var(--c-bg);overflow:auto;-webkit-transition:all ease .25s;border:1px solid var(--c-border);transition:background-color var(--t-color),border-color var(--t-color)}.gt-container .gt-comment-content{border-radius:5px}@media (max-width: 479px){.gt-container .gt-comment-content{margin-left:.875em;padding:.625em .75em}}.gt-container .gt-comment-header{margin-bottom:.75em;font-size:.875em;position:relative}.gt-container .gt-comment-block-1{float:right;height:1.375em;width:3.5em}.gt-container .gt-comment-block-2{float:right;height:1.375em;width:4em}.gt-container .gt-comment-username{font-weight:500;color:var(--c-text-accent);text-decoration:none}.gt-container .gt-comment-username:hover{text-decoration:underline}.gt-container .gt-comment-text,.gt-container .gt-comment-date{margin-left:.5em;color:#a1a1a1;font-size:.875em}.gt-container .gt-comment-like,.gt-container .gt-comment-edit,.gt-container .gt-comment-reply{position:absolute;height:1.375em}.gt-container .gt-comment-like:hover,.gt-container .gt-comment-edit:hover,.gt-container .gt-comment-reply:hover{cursor:pointer}.gt-container .gt-comment-like{top:0;right:2em}.gt-container .gt-comment-edit,.gt-container .gt-comment-reply{top:0;right:0}.gt-container .gt-comment-body{color:var(--c-text)}.gt-container .gt-comment-body .email-hidden-toggle a{display:inline-block;height:12px;padding:0 9px;font-size:12px;font-weight:600;line-height:6px;color:#444d56;text-decoration:none;vertical-align:middle;background:#dfe2e5;border-radius:1px}.gt-container .gt-comment-body .email-hidden-toggle a:hover{background-color:#c6cbd1}.gt-container .gt-comment-body .email-hidden-reply{display:none;white-space:pre-wrap}.gt-container .gt-comment-body .email-hidden-reply .email-signature-reply{padding:0 15px;margin:15px 0;color:#586069;border-left:4px solid #dfe2e5}.gt-container .gt-comment-body .email-hidden-reply.expanded{display:block}.gt-container .gt-comment-admin .gt-comment-content{background-color:var(--c-bg);border:1px solid var(--c-border)}@-webkit-keyframes gt-kf-rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes gt-kf-rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.gt-comment-body .snippet-clipboard-content pre code{color:var(--c-text)} diff --git a/development/aws/acknowledgement.html b/development/aws/acknowledgement.html index 57e871ac..54a89e37 100644 --- a/development/aws/acknowledgement.html +++ b/development/aws/acknowledgement.html @@ -5,15 +5,15 @@ 謝辞 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
    Skip to content

    謝辞

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:129
    Reading:1 min

    本原稿の執筆にあたり,以下の方々からの協力を得た.この場を借りて,感謝を表したい.

    2021 年バージョンの contributors

    • 香取真知子氏 - ハンズオンプログラムの動作確認,文章校閲

    2020 年バージョンの contributors

    • 勝俣敬寛氏 - Docker イメージの作成

    • 香取真知子氏 - ハンズオンプログラムの動作確認

    • @shuuji3 - MR !15

    • @takatama_jp - MR !14

    本書の執筆には Asciidoctor を使用した.

    また,本書はオープンソースの教科書として,すべての読者・ディベロッパーからのフィードバックを受け付けている. 誤植や記述の誤り,改善点など見つかったら,ぜひ IssuesPull request を投稿していただきたい.

    - +
    Skip to content

    謝辞

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:129
    Reading:1 min

    本原稿の執筆にあたり,以下の方々からの協力を得た.この場を借りて,感謝を表したい.

    2021 年バージョンの contributors

    • 香取真知子氏 - ハンズオンプログラムの動作確認,文章校閲

    2020 年バージョンの contributors

    • 勝俣敬寛氏 - Docker イメージの作成

    • 香取真知子氏 - ハンズオンプログラムの動作確認

    • @shuuji3 - MR !15

    • @takatama_jp - MR !14

    本書の執筆には Asciidoctor を使用した.

    また,本書はオープンソースの教科書として,すべての読者・ディベロッパーからのフィードバックを受け付けている. 誤植や記述の誤り,改善点など見つかったら,ぜひ IssuesPull request を投稿していただきたい.

    + \ No newline at end of file diff --git a/development/aws/appendix.html b/development/aws/appendix.html index 5b5a1b13..502bf284 100644 --- a/development/aws/appendix.html +++ b/development/aws/appendix.html @@ -5,16 +5,16 @@ Appendix: 環境構築 | Toshiki's Note - + - + - + - + @@ -37,38 +37,38 @@ -
    Skip to content

    Appendix: 環境構築

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:2.3k
    Reading:9 min

    本書を読み進めるにあたって,ハンズオンのプログラムを実行するための環境を自分のローカルマシンにセットアップしなければならない. ここでは, AWS やコマンドラインの初心者を想定して,本章で必要なソフトウェアやライブラリのインストールなどを簡単に解説する. 以下に簡単な目次を示そう. 既に環境構築が済んでいる場合は適宜読み飛ばしていただき,関係のある箇所のみ目を通せば良い.

    使用する OS は Linux/Mac/Windows のどれを用いても構わない. Windows のユーザーは, Windows Subsytem for Linux (WSL) を使用することを想定している (WSL のインストール).

    また,本書のハンズオンを実行するための Docker イメージ を提供している. これを用いると, AWS CLI/CDK や Python の設定などをスキップできるので, Docker の使用方法を知っている読者には便利だろう.

    AWS アカウントの取得

    本書で提供するハンズオンを実際に自分で試すには,読者自身で AWS のアカウントの作成をする必要がある. 詳しいアカウントの作成の手順は 公式のドキュメンテーション に書かれているので,そちらも参照していただきたい. 以下の手順に従ってアカウントの作成を行う.

    まず,ウェブブラウザから AWS コンソール にアクセスし,右上の Create an AWS Account をクリックする (figure_title で実線で囲った部分).

    サインアップ (1): AWS コンソールにアクセス

    次に,遷移した先のページでメールアドレスとパスワードなどの登録を行う (figure_title).

    サインアップ (2): メールアドレス・パスワードなどの登録.

    続いて,住所や電話番号などを訊かれるので,すべて入力しよう (figure_title).

    サインアップ (3): 住所・電話番号の入力

    次に,クレジットカードの情報の登録を求められる (figure_title). 個人で AWS を利用する場合は,利用料金の請求はクレジットカードを経由して行われる. クレジットカードの登録なしには AWS を使い始めることはできないことに注意.

    サインアップ (4): クレジットカードの登録

    次の画面では,携帯電話の SMS またはボイスメッセージを利用した本人確認が求められる (figure_title). 希望の認証方法を選択し,自分の携帯電話番号を入力しよう.

    サインアップ (5): 携帯電話による本人確認

    無事に本人確認が完了すると,最後にサポートプランの選択を求められる (figure_title). 無料の Basic support を選択しておけば問題ない.

    サインアップ (6): サポートプランの選択

    以上のステップにより,アカウントの作成が完了する (figure_title). 早速ログインをして, AWS コンソールにアクセスできるか確認しておこう.

    サインアップ (7): アカウントの作成が完了した

    AWS のシークレットキーの作成

    AWS シークレットキーとは, AWS CLI や AWS CDK から AWS の API を操作するときに,ユーザー認証を行うための鍵のことである. AWS CLI/CDK を使うには,最初にシークレットキーを発行する必要がある. AWS シークレットキーの詳細は 公式ドキュメンテーション "Understanding and getting your AWS credentials" を参照.

    1. AWS コンソールにログインする.

    2. 画面右上のアカウント名をクリックし,表示されるプルダウンメニューから "My Security Credentials" を選択 (figure_title)

    3. "Access keys for CLI, SDK, & API access" の下にある "Create accesss key" のボタンをクリックする (figure_title)

    4. 表示された Access key ID, Secret access key を記録しておく (画面を閉じると二度と表示されない).

    5. 鍵を忘れてしまった場合などは,同じ手順で再発行が可能である.

    6. 発行したシークレットキーは, ~/.aws/credentials のファイルに書き込むか,環境変数に設定するなどして使う (詳しくは AWS CLI のインストール).

    AWS シークレットキーの発行1

    AWS シークレットキーの発行2

    AWS Educate Starter Account を用いている場合は,次の手順でシークレットキーを確認する.

    • AWS Educate のコンソール画面から, vocareum のコンソールに移動する (figure_title).

    • Account Details をクリックし,続いて AWS CLI: Show をクリックする.

    • aws_access_key_id, aws_secret_access_key, aws_session_token が表示される (figure_title). ここで表示された内容を ~/.aws/credentials にコピーする (AWS CLI のインストール 参照). aws_session_token の箇所も漏らさずコピーすること.

    • 続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

    toml
    [default]
    -    region = us-east-1
    -    output = json
    [default]
    -    region = us-east-1
    -    output = json
    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).

    vocareum コンソール

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    sh
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +    
    Skip to content

    Appendix: 環境構築

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:2.3k
    Reading:9 min

    本書を読み進めるにあたって,ハンズオンのプログラムを実行するための環境を自分のローカルマシンにセットアップしなければならない. ここでは, AWS やコマンドラインの初心者を想定して,本章で必要なソフトウェアやライブラリのインストールなどを簡単に解説する. 以下に簡単な目次を示そう. 既に環境構築が済んでいる場合は適宜読み飛ばしていただき,関係のある箇所のみ目を通せば良い.

    使用する OS は Linux/Mac/Windows のどれを用いても構わない. Windows のユーザーは, Windows Subsytem for Linux (WSL) を使用することを想定している (WSL のインストール).

    また,本書のハンズオンを実行するための Docker イメージ を提供している. これを用いると, AWS CLI/CDK や Python の設定などをスキップできるので, Docker の使用方法を知っている読者には便利だろう.

    AWS アカウントの取得

    本書で提供するハンズオンを実際に自分で試すには,読者自身で AWS のアカウントの作成をする必要がある. 詳しいアカウントの作成の手順は 公式のドキュメンテーション に書かれているので,そちらも参照していただきたい. 以下の手順に従ってアカウントの作成を行う.

    まず,ウェブブラウザから AWS コンソール にアクセスし,右上の Create an AWS Account をクリックする (figure_title で実線で囲った部分).

    サインアップ (1): AWS コンソールにアクセス

    次に,遷移した先のページでメールアドレスとパスワードなどの登録を行う (figure_title).

    サインアップ (2): メールアドレス・パスワードなどの登録.

    続いて,住所や電話番号などを訊かれるので,すべて入力しよう (figure_title).

    サインアップ (3): 住所・電話番号の入力

    次に,クレジットカードの情報の登録を求められる (figure_title). 個人で AWS を利用する場合は,利用料金の請求はクレジットカードを経由して行われる. クレジットカードの登録なしには AWS を使い始めることはできないことに注意.

    サインアップ (4): クレジットカードの登録

    次の画面では,携帯電話の SMS またはボイスメッセージを利用した本人確認が求められる (figure_title). 希望の認証方法を選択し,自分の携帯電話番号を入力しよう.

    サインアップ (5): 携帯電話による本人確認

    無事に本人確認が完了すると,最後にサポートプランの選択を求められる (figure_title). 無料の Basic support を選択しておけば問題ない.

    サインアップ (6): サポートプランの選択

    以上のステップにより,アカウントの作成が完了する (figure_title). 早速ログインをして, AWS コンソールにアクセスできるか確認しておこう.

    サインアップ (7): アカウントの作成が完了した

    AWS のシークレットキーの作成

    AWS シークレットキーとは, AWS CLI や AWS CDK から AWS の API を操作するときに,ユーザー認証を行うための鍵のことである. AWS CLI/CDK を使うには,最初にシークレットキーを発行する必要がある. AWS シークレットキーの詳細は 公式ドキュメンテーション "Understanding and getting your AWS credentials" を参照.

    1. AWS コンソールにログインする.

    2. 画面右上のアカウント名をクリックし,表示されるプルダウンメニューから "My Security Credentials" を選択 (figure_title)

    3. "Access keys for CLI, SDK, & API access" の下にある "Create accesss key" のボタンをクリックする (figure_title)

    4. 表示された Access key ID, Secret access key を記録しておく (画面を閉じると二度と表示されない).

    5. 鍵を忘れてしまった場合などは,同じ手順で再発行が可能である.

    6. 発行したシークレットキーは, ~/.aws/credentials のファイルに書き込むか,環境変数に設定するなどして使う (詳しくは AWS CLI のインストール).

    AWS シークレットキーの発行1

    AWS シークレットキーの発行2

    AWS Educate Starter Account を用いている場合は,次の手順でシークレットキーを確認する.

    • AWS Educate のコンソール画面から, vocareum のコンソールに移動する (figure_title).

    • Account Details をクリックし,続いて AWS CLI: Show をクリックする.

    • aws_access_key_id, aws_secret_access_key, aws_session_token が表示される (figure_title). ここで表示された内容を ~/.aws/credentials にコピーする (AWS CLI のインストール 参照). aws_session_token の箇所も漏らさずコピーすること.

    • 続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

    toml
    [default]
    +    region = us-east-1
    +    output = json
    [default]
    +    region = us-east-1
    +    output = json
    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).

    vocareum コンソール

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    sh
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
     
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
     
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    本書のハンズオンではコマンドラインから AWS CLI のコマンドを実行したり, Python で書かれたプログラムを実行する. コマンドは基本的に UNIX のターミナルを想定して書かれている. Linux や Mac のユーザーは OS に標準搭載されているターミナルを用いれば良い. Windows を利用している読者は, Windows Subsystem for Linux (WSL) を利用することで,仮想の Linux 環境を構築することを推奨する. Cygwin などの Linux 環境をエミュレートするほかのツールでも構わないが,本書のプログラムは WSL でのみ動作確認を行っている.

    WSL とは, Windows の OS 上で Linux の仮想環境を起動するための, Microsoft 社が公式で提供しているソフトウェアである. Ubuntu など希望の Linux distribution が選択でき,基本的にすべての Linux 向けに作られたプログラム・ソフトウェアを使用することができる.

    執筆時点では WSL 2 が最新版として提供されているので,以下では WSL 2 のインストール手順を簡単に説明する. 細かな詳細などは, 公式ドキュメンテーション を参照のこと.

    前提として,使用される OS は Windows 10 (Pro または Home エディション) でなければならない. さらに,使用している Windows 10 のバージョンが WSL に対応するバージョンであるかを確認する. X64 のシステムでは Version 1903, Build 18362 以上でなければならない. バージョンが対応していない場合は、 Windows のアップデートを行う.

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    powershell
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    powershell
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    Ubuntu 20.04 を初回に起動すると,初期設定が自動で開始され,数分待つことになる. 初期設定が終わると,ユーザー名・パスワードを設定するようプロンプトが出るので,プロンプトに従い入力する.

    これで WSL2 のインストールが完了した. 早速 WSL2 を起動してみよう. 左下の Windows メニューの検索バーに Ubuntu と入力すると, Ubuntu 20.04 のプログラムが見つかるはずである (figure_title). クリックして起動しよう.

    Ubuntu 20.04 の起動

    すると,ターミナルの黒い画面が立ち上がるだろう (figure_title). ls, top などのコマンドを打ってみて, WSL がきちんと動作していることを確認しよう.

    WSL の起動画面

    オプションとして, Windows Terminal というマイクロソフトから提供されているツールを使うと,より快適に WSL を使用することができる. 興味のある読者はこちらのインストールも推奨する.

    Docker のインストール

    Docker のインストールの方法は OS によって異なる.

    Mac ユーザーは, Docker Desktop をインストールする. インストールの方法は, Docker のウェブサイト から, Mac 版の Docker Desktop をダウンロードし,ダウンロードされたファイルをダブルクリックし, Applications のフォルダにドラッグするだけで良い. 詳細は 公式ドキュメンテーション を参照のこと.

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    ハンズオンを実行するために必要な, Node.js, Python, AWS CDK などがインストールされた Docker image を用意した. これを使用することで,自分のローカルマシンに諸々をインストールする必要なく,すぐにハンズオンのコードが実行できる.

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    root@aws-handson:~$</programlisting>

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい ( (#sec_handson_ec2_run) など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    - +$ cat ~/.aws/config +[profile default] +region = ap-northeast-1 +output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    本書のハンズオンではコマンドラインから AWS CLI のコマンドを実行したり, Python で書かれたプログラムを実行する. コマンドは基本的に UNIX のターミナルを想定して書かれている. Linux や Mac のユーザーは OS に標準搭載されているターミナルを用いれば良い. Windows を利用している読者は, Windows Subsystem for Linux (WSL) を利用することで,仮想の Linux 環境を構築することを推奨する. Cygwin などの Linux 環境をエミュレートするほかのツールでも構わないが,本書のプログラムは WSL でのみ動作確認を行っている.

    WSL とは, Windows の OS 上で Linux の仮想環境を起動するための, Microsoft 社が公式で提供しているソフトウェアである. Ubuntu など希望の Linux distribution が選択でき,基本的にすべての Linux 向けに作られたプログラム・ソフトウェアを使用することができる.

    執筆時点では WSL 2 が最新版として提供されているので,以下では WSL 2 のインストール手順を簡単に説明する. 細かな詳細などは, 公式ドキュメンテーション を参照のこと.

    前提として,使用される OS は Windows 10 (Pro または Home エディション) でなければならない. さらに,使用している Windows 10 のバージョンが WSL に対応するバージョンであるかを確認する. X64 のシステムでは Version 1903, Build 18362 以上でなければならない. バージョンが対応していない場合は、 Windows のアップデートを行う.

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    powershell
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    powershell
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    Ubuntu 20.04 を初回に起動すると,初期設定が自動で開始され,数分待つことになる. 初期設定が終わると,ユーザー名・パスワードを設定するようプロンプトが出るので,プロンプトに従い入力する.

    これで WSL2 のインストールが完了した. 早速 WSL2 を起動してみよう. 左下の Windows メニューの検索バーに Ubuntu と入力すると, Ubuntu 20.04 のプログラムが見つかるはずである (figure_title). クリックして起動しよう.

    Ubuntu 20.04 の起動

    すると,ターミナルの黒い画面が立ち上がるだろう (figure_title). ls, top などのコマンドを打ってみて, WSL がきちんと動作していることを確認しよう.

    WSL の起動画面

    オプションとして, Windows Terminal というマイクロソフトから提供されているツールを使うと,より快適に WSL を使用することができる. 興味のある読者はこちらのインストールも推奨する.

    Docker のインストール

    Docker のインストールの方法は OS によって異なる.

    Mac ユーザーは, Docker Desktop をインストールする. インストールの方法は, Docker のウェブサイト から, Mac 版の Docker Desktop をダウンロードし,ダウンロードされたファイルをダブルクリックし, Applications のフォルダにドラッグするだけで良い. 詳細は 公式ドキュメンテーション を参照のこと.

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    ハンズオンを実行するために必要な, Node.js, Python, AWS CDK などがインストールされた Docker image を用意した. これを使用することで,自分のローカルマシンに諸々をインストールする必要なく,すぐにハンズオンのコードが実行できる.

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    root@aws-handson:~$</programlisting>

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい ( (#sec_handson_ec2_run) など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    + \ No newline at end of file diff --git a/development/aws/assignments.html b/development/aws/assignments.html index 7a5586a2..5348d18c 100644 --- a/development/aws/assignments.html +++ b/development/aws/assignments.html @@ -5,15 +5,15 @@ 課題 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ - - + + \ No newline at end of file diff --git a/development/aws/author.html b/development/aws/author.html index e32a594d..3c1adb0c 100644 --- a/development/aws/author.html +++ b/development/aws/author.html @@ -5,15 +5,15 @@ 著者紹介 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
    Skip to content

    著者紹介

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:110
    Reading:1 min

    真野 智之 (Tomoyuki Mano)

    情報理工学博士 (東京大学大学院情報理工学系研究科システム情報学専攻). 2021 年より日本学術振興会特別研究員 (PD) (現職). 沖縄科学技術大学院大学 (OIST) にてポスドク研究員として働く. 現在の研究分野は神経科学・神経情報学. 趣味は料理・ランニング・鉄道・アニメ,村上春樹の熱烈な愛読家.

    連絡先 tomoyukimano@gmail.com

    GitHub https://github.com/tomomano

    - +
    Skip to content

    著者紹介

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:110
    Reading:1 min

    真野 智之 (Tomoyuki Mano)

    情報理工学博士 (東京大学大学院情報理工学系研究科システム情報学専攻). 2021 年より日本学術振興会特別研究員 (PD) (現職). 沖縄科学技術大学院大学 (OIST) にてポスドク研究員として働く. 現在の研究分野は神経科学・神経情報学. 趣味は料理・ランニング・鉄道・アニメ,村上春樹の熱烈な愛読家.

    連絡先 tomoyukimano@gmail.com

    GitHub https://github.com/tomomano

    + \ No newline at end of file diff --git a/development/aws/aws-batch.html b/development/aws/aws-batch.html index 537a6319..ea4cde37 100644 --- a/development/aws/aws-batch.html +++ b/development/aws/aws-batch.html @@ -5,16 +5,16 @@ Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する | Toshiki's Note - + - + - + - + @@ -37,463 +37,463 @@ -
    Skip to content

    Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:5k
    Reading:20 min

    ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

    本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

    Auto scaling groups (ASG)

    ハンズオンに入っていく前に, Auto scaling groups (ASG) とよばれる EC2 の概念を知っておく必要がある.

    ECS の概要を示した (#ecs_overview) を振り返って見てほしい. 前章 ( (#sec_fargate_qabot)) でも説明したが, ECS のクラスターで計算を担う実体としては EC2 と Fargate を指定することができる. Fargate については前章で記述した. Fargate を用いると,自在にスケールする計算環境をとても簡単な設定で構築することができた. しかし, GPU を利用することができないなど,いくつかの制約があった. EC2 を使用した計算環境を指定することで,プログラミングの複雑度は増すが, GPU やその他のより高度かつ複雑な設定を伴ったクラスターを構築することができる.

    EC2 クラスターには ASG と呼ばれるサービスが配置される. ASG は複数の EC2 インスタンスをロジカルな単位でグループ化することでクラスターを構成する. ASG はクラスター内に新しいインスタンスを起動する,あるいは不要になったインスタンスを停止するなどのスケーリングを担う. ASG で重要な概念として, desired capacity, minimum capacity, maximum capacity というパラメータがある. minimum capacity, maximum capacity は,それぞれクラスター内に配置できるインスタンスの数の最小値・最大値を指定するパラメータである. 前者は,クラスターに負荷がかかっていない場合でもアイドリング状態にあるインスタンスを維持することで,急に負荷が増大した時などのバッファーとして作用することができる. 後者は,負荷が急に増えたときに,過剰な数のインスタンスが起動する事態を防ぎ,経済的なコストの上限を定める役割を果たす.

    desired capacity が,その時々でシステムが要求するインスタンスの数を指定する. desired capacity は,例えば 24 時間のリズムに合わせてインスタンスの数を増減させる (昼は多く夜は少なくなど) などの決まったスケジュールに基づいた設定を適用することができる. あるいはクラスター全体にかかっている負荷に応じて, desired capacity を動的に制御することも可能である. どのような基準でクラスターのスケーリングを行うかを定めるルールのことを,スケーリングポリシーとよぶ. たとえば,クラスター全体の稼働率 (負荷) を常に 80% に維持する,などのスケーリングポリシーが想定できる. この場合,クラスター全体の負荷が 80%を下回ったときにはクラスターからインスタンスが削除され,80%を超える (あるいは超えると予測される) 場合はインスタンスを追加する,という操作が ASG によって自動的に行われる.

    上記のようなパラメータを検討し,ユーザーは ASG を作成する. ASG を作成したのち, ECS との連携をプログラムしてあげることで, ECS を介して ASG による EC2 クラスターにタスクを投入することが可能になる.

    AWS Batch

    AWS Batch のアイコン

    先に説明したように, ECS と ASG を組み合わせることで,所望の計算クラスターを構築することが可能である. しかしながら, ECS と ASG にはかなり込み入った設定が必要であり,初心者にとっても経験者にとってもなかなか面倒なプログラミングが要求される. そこで, ECS と ASG によるクラスターの設計を自動化してくれるサービスが提供されている. それが AWS Batch である.

    AWS Batch はその名のとおりバッチ (Batch) 化されたジョブ (入力データだけが異なる独立した演算が繰り返し実行されること) を想定している. 多くの科学計算や機械学習がバッチ計算に当てはまる. たとえば,初期値のパラメータを変えて複数のシミュレーションを走らせる,といったケースだ. AWS Batch を用いることの利点は,クラスターのスケーリングやジョブの割り振りはすべて自動で実行され, ユーザーはクラウドの舞台裏の詳細を気にすることなく,大量のジョブを投入できるシステムが手に入る点である. が,知識として背後では ECS/ASG/EC2 の三つ巴が協調して動作しているという点は知っておいてほしい.

    AWS Batch では,ジョブの投入・管理をスムーズに行うため,次のような概念が定義されている (figure_title). まず, ジョブ (Job) というのが,AWS Batch によって実行される一つの計算の単位である. Job definitions とはジョブの内容を定義するものであり,これには実行されるべき Docker のイメージのアドレスや,割り当てる CPU・RAM の容量,環境変数などの設定が含まれる. Job definition に基づいて個々のジョブが実行される. ジョブが実行されると,ジョブは Job queues に入る. Job queues とは,実行待ち状態にあるジョブの列のことであり,時間的に最も先頭に投入されたジョブが最初に実行される. また,複数の queue を配置し, queue ごとに priority (優先度) を設定することが可能であり, priority の高い queue に溜まったジョブが優先的に実行される (筆者はこれをディズニーランドの"ファストパス"を連想して捉えている). Compute environment とは,先述したクラスターとほぼ同義の概念であり,計算が実行される場所 (EC2 や Fargate からなるクラスター) を指す. Compute environment には,使用する EC2 のインスタンスタイプや同時に起動するインスタンス数の上限などの簡易なスケーリングポリシーが指定されている. Job queues は Compute environment の空き状況を監視しており, それに応じてジョブを Compute environment に投下する.

    以上が AWS Batch を使用するうえで理解しておかなければならない概念であるが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは,実際に自分で手を動かしながら学んでいこう.

    AWS Batch の主要な概念

    EC2 or Fargate?

    ECS でクラスターを構成する際,計算を実行する場として EC2 と Fargate の二つの選択肢があることを説明した. それぞれ長所と短所を抱えているのだが,どのような場合にどちらを使うべきだろうか? それを検討するため,まずは table_title を見てみよう. これは EC2 と Fargate の特徴をまとめたものである. 説明の都合上,大幅な粗視化が行われている点は留意していただきたい.

    EC2 vs Fargate
    EC2Fargate

    Compute capacity

    Medium to large

    Small to medium

    GPU

    Yes

    No

    Launch speed

    Slow

    Fast

    Task placement flexibility

    Low

    High

    Programming complexity

    High

    Low

    これまでに見てきたように, EC2 は最大の CPU 数・メモリーサイズが大きかったり, GPU を利用できたりするなど,単一のインスタンスでの計算能力は高い. 対して, Fargate は単一インスタンスの最大 CPU 数は 4 コアが上限である. その一方で,インスタンスの起動に要する時間は Fargate のほうが圧倒的に早く,より俊敏にクラスターのスケーリングを行うことができる. また,タスクをクラスターに投入する際のフレキシビリティも Fargate のほうが高い. フレキシビリティというのは,例えば一つのインスタンスで 2 つ以上のコンテナを走らせる,などの状況である. 単位 CPU あたりで処理されるタスクの数を最大化する際には,このような設計がしばしば採用される. プログラミングの複雑さという観点からは, Fargate のほうが一般的にシンプルな実装になる.

    このように, EC2 と Fargate は互いに相補的な特性を有しており,アプリケーションによって最適な計算環境は検討される必要がある. また,EC2 と Fargate を両方用いたハイブリッドクラスターというのも定義可能であり,そのような選択肢もしばしば用いられる.

    準備

    ハンズオンのソースコードは GitHub の handson/aws-batch にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,アメリカ東部 (us-east-1) リージョンでは 0.526 $/hour のコストが発生する. 東京 (ap-northeast-1) を選択した場合は 0.71 $/hour のコストが発生する.

    (#sec:jupyter_and_deep_learning_setup) でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, (#sec_mnist_using_jupyter) で扱った MNIST 手書き文字認識の問題を再度取り上げよう. (#sec_mnist_using_jupyter) では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    ランダムサーチ法とは,ハイパーパラメータの組をある範囲の中でランダムに抽出し,大量に試行されたランダムな組の中から最適なパラメータの組を見出す方法である. すべての可能性を網羅的に探索できるわけではないが,調整すべきパラメータの数が多数ある場合に,グリッドサーチよりも効率的に広い探索空間をカバーすることができる.

    ベイズ最適化を用いた方法では,過去の探索結果から次にどの組み合わせを探索すべきかという指標を計算し,次に探索するパラメータを決定する. これにより,理論的にはグリッドサーチやランダムサーチ法よりも少ない試行回数で最適なパラメータにたどり着くことができる.

    並列化の観点でいうと,グリッドサーチとランダムサーチは各ハイパーパラメータの組の計算は独立に実行することができるため並列化が容易である. このように独立したジョブとして分割・並列化可能な問題を Embarrassingly parallel な問題とよぶ (直訳すると"恥ずかしいほど並列化可能な問題",ということになる). Embarrassingly parallel な問題はクラウドの強力な計算リソースを用いることで,非常なシンプルな実装で解くことができる. この章ではこのようなタイプの並列計算を取り上げる.

    一方,ベイズ最適化による方法は,過去の結果をもとに次の探索が決定されるので,並列化はそれほど単純ではない. 最近では optuna などのハイパーパラメータ探索のためのライブラリが発達しており,ベイズ最適化の数理的な処理を自動で実行してくれるので便利である. これらのライブラリを使うと,もし一台のコンピュータ (ノード) の中に複数の GPU が存在する場合は,並列に計算を実行することができる. しかしながら,一台のノードにとどまらず,複数のノードをまたいだ並列化は,高度なプログラミングテクニックが必要とされるだけでなく,ノード間の接続様式などクラウドのアーキテクチャにも深く依存するものである. 本書ではここまで高度なクラウドの使用方法には立ち入らない.

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に (#sec_mnist_using_jupyter) のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    sh
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. (#sec_jupyter_and_deep_learning) のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    -

    このコマンドでは,--gpus all というパラメータが加わった.

    CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

    (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

    これはオーバーフィッティングとよばれる現象で,ニューラルネットが訓練データに過度に最適化され,訓練データの外のデータに対しての精度 (汎化性能) が向上していないことを示している. このような場合の対処法として, Early stopping とよばれるテクニックが知られている. Early stopping とは,検証データの Loss を追跡し,それが減少から増加に転じるエポックで学習をうち止め,そのエポックでのウェイトパラメータを採用する,というものである. 本ハンズオンでも, Early stopping によって訓練の終了を判断し,モデルの性能評価を行っていく.

    MNIST 手書き文字データセットでは,訓練データとして 60,000 枚,テストデータとして 10,000 枚の画像が与えられている. 本ハンズオンで使用するコードでは,訓練データのうち 80% の 48,000 枚を訓練データとして使用し,残り 20% の 12,000 枚を検証データとして用いている. 詳しくはソースコードを参照のこと.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントは,あるハイパーパラメータの組を指定して Batch にジョブを提出する

    • Batch はジョブを受け取ると, EC2 からなるクラスターで計算を実行する

    • クラスター内では g4dn.xlarge インスタンスが起動する

    • Docker イメージは, AWS 内に用意された ECR (Elastic Container Registry) から取得される

    • 複数のジョブが投下された場合は,その数だけのインスタンスが起動し並列に実行される

    • 各ジョブによる計算の結果は S3 に保存される

    • 最後にクライアントは S3 から結果をダウンロードし,最適なハイパーパラメータの組を決定する

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    python
    class SimpleBatch(core.Stack):
    +    
    Skip to content

    Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:5k
    Reading:20 min

    ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

    本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

    Auto scaling groups (ASG)

    ハンズオンに入っていく前に, Auto scaling groups (ASG) とよばれる EC2 の概念を知っておく必要がある.

    ECS の概要を示した (#ecs_overview) を振り返って見てほしい. 前章 ( (#sec_fargate_qabot)) でも説明したが, ECS のクラスターで計算を担う実体としては EC2 と Fargate を指定することができる. Fargate については前章で記述した. Fargate を用いると,自在にスケールする計算環境をとても簡単な設定で構築することができた. しかし, GPU を利用することができないなど,いくつかの制約があった. EC2 を使用した計算環境を指定することで,プログラミングの複雑度は増すが, GPU やその他のより高度かつ複雑な設定を伴ったクラスターを構築することができる.

    EC2 クラスターには ASG と呼ばれるサービスが配置される. ASG は複数の EC2 インスタンスをロジカルな単位でグループ化することでクラスターを構成する. ASG はクラスター内に新しいインスタンスを起動する,あるいは不要になったインスタンスを停止するなどのスケーリングを担う. ASG で重要な概念として, desired capacity, minimum capacity, maximum capacity というパラメータがある. minimum capacity, maximum capacity は,それぞれクラスター内に配置できるインスタンスの数の最小値・最大値を指定するパラメータである. 前者は,クラスターに負荷がかかっていない場合でもアイドリング状態にあるインスタンスを維持することで,急に負荷が増大した時などのバッファーとして作用することができる. 後者は,負荷が急に増えたときに,過剰な数のインスタンスが起動する事態を防ぎ,経済的なコストの上限を定める役割を果たす.

    desired capacity が,その時々でシステムが要求するインスタンスの数を指定する. desired capacity は,例えば 24 時間のリズムに合わせてインスタンスの数を増減させる (昼は多く夜は少なくなど) などの決まったスケジュールに基づいた設定を適用することができる. あるいはクラスター全体にかかっている負荷に応じて, desired capacity を動的に制御することも可能である. どのような基準でクラスターのスケーリングを行うかを定めるルールのことを,スケーリングポリシーとよぶ. たとえば,クラスター全体の稼働率 (負荷) を常に 80% に維持する,などのスケーリングポリシーが想定できる. この場合,クラスター全体の負荷が 80%を下回ったときにはクラスターからインスタンスが削除され,80%を超える (あるいは超えると予測される) 場合はインスタンスを追加する,という操作が ASG によって自動的に行われる.

    上記のようなパラメータを検討し,ユーザーは ASG を作成する. ASG を作成したのち, ECS との連携をプログラムしてあげることで, ECS を介して ASG による EC2 クラスターにタスクを投入することが可能になる.

    AWS Batch

    AWS Batch のアイコン

    先に説明したように, ECS と ASG を組み合わせることで,所望の計算クラスターを構築することが可能である. しかしながら, ECS と ASG にはかなり込み入った設定が必要であり,初心者にとっても経験者にとってもなかなか面倒なプログラミングが要求される. そこで, ECS と ASG によるクラスターの設計を自動化してくれるサービスが提供されている. それが AWS Batch である.

    AWS Batch はその名のとおりバッチ (Batch) 化されたジョブ (入力データだけが異なる独立した演算が繰り返し実行されること) を想定している. 多くの科学計算や機械学習がバッチ計算に当てはまる. たとえば,初期値のパラメータを変えて複数のシミュレーションを走らせる,といったケースだ. AWS Batch を用いることの利点は,クラスターのスケーリングやジョブの割り振りはすべて自動で実行され, ユーザーはクラウドの舞台裏の詳細を気にすることなく,大量のジョブを投入できるシステムが手に入る点である. が,知識として背後では ECS/ASG/EC2 の三つ巴が協調して動作しているという点は知っておいてほしい.

    AWS Batch では,ジョブの投入・管理をスムーズに行うため,次のような概念が定義されている (figure_title). まず, ジョブ (Job) というのが,AWS Batch によって実行される一つの計算の単位である. Job definitions とはジョブの内容を定義するものであり,これには実行されるべき Docker のイメージのアドレスや,割り当てる CPU・RAM の容量,環境変数などの設定が含まれる. Job definition に基づいて個々のジョブが実行される. ジョブが実行されると,ジョブは Job queues に入る. Job queues とは,実行待ち状態にあるジョブの列のことであり,時間的に最も先頭に投入されたジョブが最初に実行される. また,複数の queue を配置し, queue ごとに priority (優先度) を設定することが可能であり, priority の高い queue に溜まったジョブが優先的に実行される (筆者はこれをディズニーランドの"ファストパス"を連想して捉えている). Compute environment とは,先述したクラスターとほぼ同義の概念であり,計算が実行される場所 (EC2 や Fargate からなるクラスター) を指す. Compute environment には,使用する EC2 のインスタンスタイプや同時に起動するインスタンス数の上限などの簡易なスケーリングポリシーが指定されている. Job queues は Compute environment の空き状況を監視しており, それに応じてジョブを Compute environment に投下する.

    以上が AWS Batch を使用するうえで理解しておかなければならない概念であるが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは,実際に自分で手を動かしながら学んでいこう.

    AWS Batch の主要な概念

    EC2 or Fargate?

    ECS でクラスターを構成する際,計算を実行する場として EC2 と Fargate の二つの選択肢があることを説明した. それぞれ長所と短所を抱えているのだが,どのような場合にどちらを使うべきだろうか? それを検討するため,まずは table_title を見てみよう. これは EC2 と Fargate の特徴をまとめたものである. 説明の都合上,大幅な粗視化が行われている点は留意していただきたい.

    EC2 vs Fargate
    EC2Fargate

    Compute capacity

    Medium to large

    Small to medium

    GPU

    Yes

    No

    Launch speed

    Slow

    Fast

    Task placement flexibility

    Low

    High

    Programming complexity

    High

    Low

    これまでに見てきたように, EC2 は最大の CPU 数・メモリーサイズが大きかったり, GPU を利用できたりするなど,単一のインスタンスでの計算能力は高い. 対して, Fargate は単一インスタンスの最大 CPU 数は 4 コアが上限である. その一方で,インスタンスの起動に要する時間は Fargate のほうが圧倒的に早く,より俊敏にクラスターのスケーリングを行うことができる. また,タスクをクラスターに投入する際のフレキシビリティも Fargate のほうが高い. フレキシビリティというのは,例えば一つのインスタンスで 2 つ以上のコンテナを走らせる,などの状況である. 単位 CPU あたりで処理されるタスクの数を最大化する際には,このような設計がしばしば採用される. プログラミングの複雑さという観点からは, Fargate のほうが一般的にシンプルな実装になる.

    このように, EC2 と Fargate は互いに相補的な特性を有しており,アプリケーションによって最適な計算環境は検討される必要がある. また,EC2 と Fargate を両方用いたハイブリッドクラスターというのも定義可能であり,そのような選択肢もしばしば用いられる.

    準備

    ハンズオンのソースコードは GitHub の handson/aws-batch にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,アメリカ東部 (us-east-1) リージョンでは 0.526 $/hour のコストが発生する. 東京 (ap-northeast-1) を選択した場合は 0.71 $/hour のコストが発生する.

    (#sec:jupyter_and_deep_learning_setup) でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, (#sec_mnist_using_jupyter) で扱った MNIST 手書き文字認識の問題を再度取り上げよう. (#sec_mnist_using_jupyter) では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    ランダムサーチ法とは,ハイパーパラメータの組をある範囲の中でランダムに抽出し,大量に試行されたランダムな組の中から最適なパラメータの組を見出す方法である. すべての可能性を網羅的に探索できるわけではないが,調整すべきパラメータの数が多数ある場合に,グリッドサーチよりも効率的に広い探索空間をカバーすることができる.

    ベイズ最適化を用いた方法では,過去の探索結果から次にどの組み合わせを探索すべきかという指標を計算し,次に探索するパラメータを決定する. これにより,理論的にはグリッドサーチやランダムサーチ法よりも少ない試行回数で最適なパラメータにたどり着くことができる.

    並列化の観点でいうと,グリッドサーチとランダムサーチは各ハイパーパラメータの組の計算は独立に実行することができるため並列化が容易である. このように独立したジョブとして分割・並列化可能な問題を Embarrassingly parallel な問題とよぶ (直訳すると"恥ずかしいほど並列化可能な問題",ということになる). Embarrassingly parallel な問題はクラウドの強力な計算リソースを用いることで,非常なシンプルな実装で解くことができる. この章ではこのようなタイプの並列計算を取り上げる.

    一方,ベイズ最適化による方法は,過去の結果をもとに次の探索が決定されるので,並列化はそれほど単純ではない. 最近では optuna などのハイパーパラメータ探索のためのライブラリが発達しており,ベイズ最適化の数理的な処理を自動で実行してくれるので便利である. これらのライブラリを使うと,もし一台のコンピュータ (ノード) の中に複数の GPU が存在する場合は,並列に計算を実行することができる. しかしながら,一台のノードにとどまらず,複数のノードをまたいだ並列化は,高度なプログラミングテクニックが必要とされるだけでなく,ノード間の接続様式などクラウドのアーキテクチャにも深く依存するものである. 本書ではここまで高度なクラウドの使用方法には立ち入らない.

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に (#sec_mnist_using_jupyter) のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    sh
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. (#sec_jupyter_and_deep_learning) のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    +

    このコマンドでは,--gpus all というパラメータが加わった.

    CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

    (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

    これはオーバーフィッティングとよばれる現象で,ニューラルネットが訓練データに過度に最適化され,訓練データの外のデータに対しての精度 (汎化性能) が向上していないことを示している. このような場合の対処法として, Early stopping とよばれるテクニックが知られている. Early stopping とは,検証データの Loss を追跡し,それが減少から増加に転じるエポックで学習をうち止め,そのエポックでのウェイトパラメータを採用する,というものである. 本ハンズオンでも, Early stopping によって訓練の終了を判断し,モデルの性能評価を行っていく.

    MNIST 手書き文字データセットでは,訓練データとして 60,000 枚,テストデータとして 10,000 枚の画像が与えられている. 本ハンズオンで使用するコードでは,訓練データのうち 80% の 48,000 枚を訓練データとして使用し,残り 20% の 12,000 枚を検証データとして用いている. 詳しくはソースコードを参照のこと.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントは,あるハイパーパラメータの組を指定して Batch にジョブを提出する

    • Batch はジョブを受け取ると, EC2 からなるクラスターで計算を実行する

    • クラスター内では g4dn.xlarge インスタンスが起動する

    • Docker イメージは, AWS 内に用意された ECR (Elastic Container Registry) から取得される

    • 複数のジョブが投下された場合は,その数だけのインスタンスが起動し並列に実行される

    • 各ジョブによる計算の結果は S3 に保存される

    • 最後にクライアントは S3 から結果をダウンロードし,最適なハイパーパラメータの組を決定する

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    python
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    class SimpleBatch(core.Stack):
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    • で,計算結果を保存するための S3 バケットを用意している

    • で, Compute environment を定義している. ここでは g4dn.xlarge のインスタンスタイプを使用するとし,最大の vCPU 使用数は 64 と指定している. また,最小の vCPU は 0 である. 今回は,負荷がかかっていないときにアイドリング状態にあるインスタンスを用意する利点は全くないので,ここは 0 にするのが望ましい.

    • で, <2> で作成した Compute environment と紐付いた Job queue を定義している.

    • で,ジョブが計算結果を S3 に書き込むことができるよう, IAM ロールを定義している. (IAM とはリソースがもつ権限を管理する仕組みである.詳しくは (#sec:bashoutter_iam) を参照)

    • では, Docker image を配置するための ECR を定義している.

    • で Job definition を作成している. ここでは,4 vCPU, 12000 MB (=12GB) の RAM を使用するように指定している. また,今後必要となる環境変数 (BUCKET_NAME) を設定している. さらに, <4> で作った IAM を付与している.

    g4dn.xlarge は 1 台あたり 4 vCPU が割り当てられている. このプログラムでは Compute environment の maximum vCPUs を 64 と指定しているので,最大で 16 台のインスタンスが同時に起動することになる. ここで maxium vCPUs を 64 に限定しているのは,なんらかのミスで意図せぬジョブを大量にクラスターに投入してしまった事態で,高額の AWS 利用料金が発生するのを防ぐためである. もし,自分のアプリケーションで必要と判断したならば自己責任において 64 よりも大きな数を設定して構わない.

    ここで注意が一点ある. AWS では各アカウントごとに EC2 で起動できるインスタンスの上限が設定されている. この上限は AWS コンソールにログインし, EC2 コンソールの左側メニューバーの Limits をクリックすることで確認できる (figure_title). g4dn.xlarge (EC2 の区分でいうと G ファミリーに属する) の制限を確認するには, Running On-Demand All G instances という名前の項目を見る. ここにある数字が, AWS によって課されたアカウントの上限であり,この上限を超えたインスタンスを起動することはできない. もし,自分の用途に対して上限が低すぎる場合は,上限の緩和申請を行うことができる. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    EC2コンソールから各種の上限を確認する

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    • で,計算結果を保存するための S3 バケットを用意している

    • で, Compute environment を定義している. ここでは g4dn.xlarge のインスタンスタイプを使用するとし,最大の vCPU 使用数は 64 と指定している. また,最小の vCPU は 0 である. 今回は,負荷がかかっていないときにアイドリング状態にあるインスタンスを用意する利点は全くないので,ここは 0 にするのが望ましい.

    • で, <2> で作成した Compute environment と紐付いた Job queue を定義している.

    • で,ジョブが計算結果を S3 に書き込むことができるよう, IAM ロールを定義している. (IAM とはリソースがもつ権限を管理する仕組みである.詳しくは (#sec:bashoutter_iam) を参照)

    • では, Docker image を配置するための ECR を定義している.

    • で Job definition を作成している. ここでは,4 vCPU, 12000 MB (=12GB) の RAM を使用するように指定している. また,今後必要となる環境変数 (BUCKET_NAME) を設定している. さらに, <4> で作った IAM を付与している.

    g4dn.xlarge は 1 台あたり 4 vCPU が割り当てられている. このプログラムでは Compute environment の maximum vCPUs を 64 と指定しているので,最大で 16 台のインスタンスが同時に起動することになる. ここで maxium vCPUs を 64 に限定しているのは,なんらかのミスで意図せぬジョブを大量にクラスターに投入してしまった事態で,高額の AWS 利用料金が発生するのを防ぐためである. もし,自分のアプリケーションで必要と判断したならば自己責任において 64 よりも大きな数を設定して構わない.

    ここで注意が一点ある. AWS では各アカウントごとに EC2 で起動できるインスタンスの上限が設定されている. この上限は AWS コンソールにログインし, EC2 コンソールの左側メニューバーの Limits をクリックすることで確認できる (figure_title). g4dn.xlarge (EC2 の区分でいうと G ファミリーに属する) の制限を確認するには, Running On-Demand All G instances という名前の項目を見る. ここにある数字が, AWS によって課されたアカウントの上限であり,この上限を超えたインスタンスを起動することはできない. もし,自分の用途に対して上限が低すぎる場合は,上限の緩和申請を行うことができる. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    EC2コンソールから各種の上限を確認する

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    次に,Job queue overview にある SimpleBatch-queue という項目に注目してほしい. ここでは実行待ちのジョブ・実行中のジョブ・実行が完了したジョブを一覧で確認することができる. PENDING, RUNNING, SUCCEEDED, FAILED などのカラムがあることが確認できる.ジョブが進行するにつれて,ジョブの状態がこのカラムにしたがって遷移していく. 後でジョブを実際にサブミットしたときに戻ってこよう.

    最後に,今回作成した Job definition を確認しよう. 左側のメニューから Job definitions を選択し,次の画面で SimpleBatchjob-definition という項目を見つけて開く. ここから Job definition の詳細を閲覧することができる (figure_title). 中でも重要な情報としては, vCPUs, Memory, GPU がそれぞれ Docker に割り当てられる vCPU・メモリー・ GPU の量を規定している. また, Image と書いてあるところに,ジョブで使用される Docker イメージが指定されている. ここでは, ECR のレポジトリを参照している. 現時点ではこの ECR は空である. 次のステップとして,この ECR にイメージを配置する作業を行おう.

    AWS Batch から Job definition を確認

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン ( (#sec_fargate_qabot)) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    python
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    次に,Job queue overview にある SimpleBatch-queue という項目に注目してほしい. ここでは実行待ちのジョブ・実行中のジョブ・実行が完了したジョブを一覧で確認することができる. PENDING, RUNNING, SUCCEEDED, FAILED などのカラムがあることが確認できる.ジョブが進行するにつれて,ジョブの状態がこのカラムにしたがって遷移していく. 後でジョブを実際にサブミットしたときに戻ってこよう.

    最後に,今回作成した Job definition を確認しよう. 左側のメニューから Job definitions を選択し,次の画面で SimpleBatchjob-definition という項目を見つけて開く. ここから Job definition の詳細を閲覧することができる (figure_title). 中でも重要な情報としては, vCPUs, Memory, GPU がそれぞれ Docker に割り当てられる vCPU・メモリー・ GPU の量を規定している. また, Image と書いてあるところに,ジョブで使用される Docker イメージが指定されている. ここでは, ECR のレポジトリを参照している. 現時点ではこの ECR は空である. 次のステップとして,この ECR にイメージを配置する作業を行おう.

    AWS Batch から Job definition を確認

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン ( (#sec_fargate_qabot)) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    python
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
     
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
     
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    • で,新規の ECR を作成している.

    • で Job definition を定義する中で,イメージを <1> で作った ECR から取得するように指定している. これと同時に, Job definition には ECR へのアクセス権限が IAM を通じて自動的に付与される.

    さて,スタックをデプロイした時点では, ECR は空っぽである. ここに自分のアプリケーションで使う Docker イメージを push してあげる必要がある.

    そのために,まずは AWS コンソールから ECR の画面を開こう (検索バーに Elastic Container Registry と入力すると出てくる). Private というタブを選択すると, simplebatch-repositoryXXXXXX という名前のレポジトリが見つかるだろう (figure_title).

    ECR のコンソール画面

    次に,このレポジトリの名前をクリックするとレポジトリの詳細画面に遷移する. そうしたら,画面右上にある View push commands というボタンをクリックする. すると figure_title のようなポップアップ画面が立ち上がる.

    ECR への push コマンド

    このポップアップ画面で表示されている四つのコマンドを順番に実行していくことで,手元の Docker イメージを ECR に push することができる. push を実行する前に, AWS の認証情報が設定されていることを確認しよう. そのうえで,ハンズオンのソースコードの中にある docker/ という名前のディレクトリに移動する. そうしたら,ポップアップ画面で表示されたコマンドを上から順に実行していく.

    ポップアップで表示されるコマンドの 2 つめを見てみると docker build -t XXXXX . となっている. 最後の . が重要で,これは 現在のディレクトリにある Dockerfile を使ってイメージをビルドせよ という意味である. このような理由で, Dockerfile が置いてあるディレクトリに移動する必要がある.

    四つ目のコマンドは,数 GB あるイメージを ECR にアップロードするので少し時間がかかるかもしれないが,これが完了するとめでたくイメージが ECR に配置されたことになる. もう一度 ECR のコンソールを見てみると,確かにイメージが配置されていることが確認できる (figure_title). これで,AWS Batch を使ってジョブを実行させるための最後の準備が完了した.

    ECR へ image の配置が完了した

    単一のジョブを実行する

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    sh
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    python
    # [1]
    -import boto3
    -import argparse
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    • で,新規の ECR を作成している.

    • で Job definition を定義する中で,イメージを <1> で作った ECR から取得するように指定している. これと同時に, Job definition には ECR へのアクセス権限が IAM を通じて自動的に付与される.

    さて,スタックをデプロイした時点では, ECR は空っぽである. ここに自分のアプリケーションで使う Docker イメージを push してあげる必要がある.

    そのために,まずは AWS コンソールから ECR の画面を開こう (検索バーに Elastic Container Registry と入力すると出てくる). Private というタブを選択すると, simplebatch-repositoryXXXXXX という名前のレポジトリが見つかるだろう (figure_title).

    ECR のコンソール画面

    次に,このレポジトリの名前をクリックするとレポジトリの詳細画面に遷移する. そうしたら,画面右上にある View push commands というボタンをクリックする. すると figure_title のようなポップアップ画面が立ち上がる.

    ECR への push コマンド

    このポップアップ画面で表示されている四つのコマンドを順番に実行していくことで,手元の Docker イメージを ECR に push することができる. push を実行する前に, AWS の認証情報が設定されていることを確認しよう. そのうえで,ハンズオンのソースコードの中にある docker/ という名前のディレクトリに移動する. そうしたら,ポップアップ画面で表示されたコマンドを上から順に実行していく.

    ポップアップで表示されるコマンドの 2 つめを見てみると docker build -t XXXXX . となっている. 最後の . が重要で,これは 現在のディレクトリにある Dockerfile を使ってイメージをビルドせよ という意味である. このような理由で, Dockerfile が置いてあるディレクトリに移動する必要がある.

    四つ目のコマンドは,数 GB あるイメージを ECR にアップロードするので少し時間がかかるかもしれないが,これが完了するとめでたくイメージが ECR に配置されたことになる. もう一度 ECR のコンソールを見てみると,確かにイメージが配置されていることが確認できる (figure_title). これで,AWS Batch を使ってジョブを実行させるための最後の準備が完了した.

    ECR へ image の配置が完了した

    単一のジョブを実行する

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    sh
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    python
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
     
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    -import boto3
    -import argparse
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
     
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    python
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    python
    # [4]
    -submit_job(0.01, 0.1, 100)
    # [4]
    -submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは (#aws_cli_install)), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    AWS Batch でジョブが実行されている様子

    figure_title で赤で囲った箇所に注目してほしい. 一つのジョブが投入されると,それは SUBMITTED という状態を経て RUNNABLE という状態に遷移する. RUNNABLE とは, ジョブを実行するためのインスタンスが Compute environment に不足しているため,新たなインスタンスが起動されるのを待っている状態に相当する. インスタンスの準備が整うと,ジョブの状態は STARTING を経て RUNNING に至る.

    次に,ジョブのステータスが RUNNING のときの Compute environment の Desired vCPU を見てみよう (figure_title で紫で囲った箇所). ここで 4 と表示されているのは, g4dn.xlarge インスタンス一つ分の vCPU の数である. ジョブの投入に応じて,それを実行するのに最低限必要な EC2 インスタンスが起動されたことが確認できる (興味のある人は, EC2 コンソールも同時に覗いてみるとよい).

    しばらく経つと,ジョブの状態は RUNNING から SUCCEEDED (あるいは何らかの理由でエラーが発生したときには FAILED) に遷移する. 今回のハンズオンで使っている MNIST の学習はだいたい 10 分くらいで完了するはずである. ジョブの状態が SUCCEEDED になるまで見届けよう.

    ジョブが完了すると,学習の結果 (エポックごとの Loss と Accuracy を記録した CSV ファイル) は S3 に保存される. AWS コンソールからこれを確認しよう.

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    python
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    python
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    python
    # [4]
    +submit_job(0.01, 0.1, 100)
    # [4]
    +submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは (#aws_cli_install)), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    AWS Batch でジョブが実行されている様子

    figure_title で赤で囲った箇所に注目してほしい. 一つのジョブが投入されると,それは SUBMITTED という状態を経て RUNNABLE という状態に遷移する. RUNNABLE とは, ジョブを実行するためのインスタンスが Compute environment に不足しているため,新たなインスタンスが起動されるのを待っている状態に相当する. インスタンスの準備が整うと,ジョブの状態は STARTING を経て RUNNING に至る.

    次に,ジョブのステータスが RUNNING のときの Compute environment の Desired vCPU を見てみよう (figure_title で紫で囲った箇所). ここで 4 と表示されているのは, g4dn.xlarge インスタンス一つ分の vCPU の数である. ジョブの投入に応じて,それを実行するのに最低限必要な EC2 インスタンスが起動されたことが確認できる (興味のある人は, EC2 コンソールも同時に覗いてみるとよい).

    しばらく経つと,ジョブの状態は RUNNING から SUCCEEDED (あるいは何らかの理由でエラーが発生したときには FAILED) に遷移する. 今回のハンズオンで使っている MNIST の学習はだいたい 10 分くらいで完了するはずである. ジョブの状態が SUCCEEDED になるまで見届けよう.

    ジョブが完了すると,学習の結果 (エポックごとの Loss と Accuracy を記録した CSV ファイル) は S3 に保存される. AWS コンソールからこれを確認しよう.

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    python
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    python
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    python
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
     
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
     
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
     
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
     
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
     
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
     
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    python
    # [1]
    -import boto3
    -import argparse
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    python
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    # [1]
    -import boto3
    -import argparse
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    python
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    複数のジョブを同時投入したときの Job 一覧

    今度は EC2 コンソールを見てみよう. 左のメニューから Instances を選択すると, figure_title に示すような起動中のインスタンスの一覧が表示される. g4dn.xlarge が 9 台稼働しているのが確認できる. Batch がジョブの投下に合わせて必要な数のインスタンスを起動してくれたのだ!

    複数のジョブを同時投入したときの EC2 インスタンスの一覧

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    python
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    python
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    複数のジョブを同時投入したときの Job 一覧

    今度は EC2 コンソールを見てみよう. 左のメニューから Instances を選択すると, figure_title に示すような起動中のインスタンスの一覧が表示される. g4dn.xlarge が 9 台稼働しているのが確認できる. Batch がジョブの投下に合わせて必要な数のインスタンスを起動してくれたのだ!

    複数のジョブを同時投入したときの EC2 インスタンスの一覧

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    python
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
     
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
     
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
     
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
     
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
     
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
     
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    今回のパラメータサーチは勉強用に極めて単純化されたものである点は承知いただきたい.

    たとえば,今回は学習率が 0.1 が最も良いとされたが,それは訓練のエポックを 100 に限定しているからかもしれない. 学習率が低いとその分訓練に必要なエポック数も多くなる. 訓練のエポック数をもっと増やせばまた違った結果が観察される可能性はある.

    また,今回は MNIST の訓練データ 60,000 枚のうち, 48,000 枚を訓練データ,残り 12,000 枚を検証データとして用いた. この分割は乱数を固定してランダムに行ったが,もしこの分割によるデータのバイアスを気にするならば, k 個の異なる学習・検証データの分割をあらかじめ用意して,複数回モデルの評価を行う (k-fold cross-validation) 方法も,より精緻なアプローチとして考えられる.

    以上のようにして, CNN を用いた MNIST 分類モデルのハイパーパラメータの最適化の一連の流れを体験した. AWS Batch を利用することで,比較的少ないプログラミングで,動的に EC2 クラスターを制御し,並列にジョブを処理するシステムが構築できた. ここまで EC2 を使いこなすことができれば,多くの問題を自力で解くことが可能になるだろう!

    スタックの削除

    これにて,本ハンズオンは終了である.最後にスタックを削除しよう. 今回のスタックを削除するにあたり,ECR に配置された Docker のイメージは手動で削除されなければならない (これをしないと, cdk destroy を実行したときにエラーになってしまう. これは CloudFormation の仕様なので従うしかない).

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, (#sec_jupyter_and_deep_learning) で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを (#sec_fargate_qabot) を参考に構築する.

    実際,本書ではこの流れに沿って演習を進めてきた. MNIST タスクを解くモデルを,最初 Jupyter Notebook を使用して実験し,そのコードをほとんどそのまま Docker にパッケージし, AWS Batch を用いてハイパーパラメータサーチを行った. このサイクルを繰り返すことで,クラウドを最大限に活用した機械学習アプリケーションの開発を進めることができる.

    クラウドを活用した機械学習アプリケーションの開発フロー

    小括

    ここまでが,本書第二部の内容である. 第一部に引き続き盛りだくさんの内容であったが,ついてこれたであろうか?

    第二部ではまず最初に,深層学習の計算をクラウドで実行するため, GPU 搭載型の EC2 インスタンスの起動について解説した. さらに,ハンズオンでは,クラウドに起動した仮想サーバーを使って MNIST 文字認識タスクを解くニューラルネットを訓練した ( (#sec_jupyter_and_deep_learning)).

    また,より大規模な機械学習アプリケーションを作るための手段として, Docker と ECS によるクラスターの初歩を説明した ( (#sec_docker_introduction)). その応用として,英語で与えられた文章問題への回答を自動で生成するボットをクラウドに展開した ( (#sec_fargate_qabot)). タスクの投入に応じて動的に計算リソースが作成・削除される様子を実際に体験できただろう.

    さらに, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する では AWS Batch を用いてニューラルネットの学習を並列に実行する方法を紹介した. ここで紹介した方法は,ミニマムであるが,計算機システムを大規模化していくためのエッセンスが網羅されている. これらのハンズオン体験から,クラウド技術を応用してどのように現実世界の問題を解いていくのか,なんとなくイメージが伝わっただろうか?

    本書の第三部では,さらにレベルアップし,サーバーレスアーキテクチャという最新のクラウドの設計手法について解説する. その応用として,ハンズオンでは簡単な SNS サービスをゼロから実装する. 引き続きクラウドの最先端の世界を楽しんでいこう!

    - +for i in range(3): + for j in range(3): + text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}", + ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    今回のパラメータサーチは勉強用に極めて単純化されたものである点は承知いただきたい.

    たとえば,今回は学習率が 0.1 が最も良いとされたが,それは訓練のエポックを 100 に限定しているからかもしれない. 学習率が低いとその分訓練に必要なエポック数も多くなる. 訓練のエポック数をもっと増やせばまた違った結果が観察される可能性はある.

    また,今回は MNIST の訓練データ 60,000 枚のうち, 48,000 枚を訓練データ,残り 12,000 枚を検証データとして用いた. この分割は乱数を固定してランダムに行ったが,もしこの分割によるデータのバイアスを気にするならば, k 個の異なる学習・検証データの分割をあらかじめ用意して,複数回モデルの評価を行う (k-fold cross-validation) 方法も,より精緻なアプローチとして考えられる.

    以上のようにして, CNN を用いた MNIST 分類モデルのハイパーパラメータの最適化の一連の流れを体験した. AWS Batch を利用することで,比較的少ないプログラミングで,動的に EC2 クラスターを制御し,並列にジョブを処理するシステムが構築できた. ここまで EC2 を使いこなすことができれば,多くの問題を自力で解くことが可能になるだろう!

    スタックの削除

    これにて,本ハンズオンは終了である.最後にスタックを削除しよう. 今回のスタックを削除するにあたり,ECR に配置された Docker のイメージは手動で削除されなければならない (これをしないと, cdk destroy を実行したときにエラーになってしまう. これは CloudFormation の仕様なので従うしかない).

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, (#sec_jupyter_and_deep_learning) で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを (#sec_fargate_qabot) を参考に構築する.

    実際,本書ではこの流れに沿って演習を進めてきた. MNIST タスクを解くモデルを,最初 Jupyter Notebook を使用して実験し,そのコードをほとんどそのまま Docker にパッケージし, AWS Batch を用いてハイパーパラメータサーチを行った. このサイクルを繰り返すことで,クラウドを最大限に活用した機械学習アプリケーションの開発を進めることができる.

    クラウドを活用した機械学習アプリケーションの開発フロー

    小括

    ここまでが,本書第二部の内容である. 第一部に引き続き盛りだくさんの内容であったが,ついてこれたであろうか?

    第二部ではまず最初に,深層学習の計算をクラウドで実行するため, GPU 搭載型の EC2 インスタンスの起動について解説した. さらに,ハンズオンでは,クラウドに起動した仮想サーバーを使って MNIST 文字認識タスクを解くニューラルネットを訓練した ( (#sec_jupyter_and_deep_learning)).

    また,より大規模な機械学習アプリケーションを作るための手段として, Docker と ECS によるクラスターの初歩を説明した ( (#sec_docker_introduction)). その応用として,英語で与えられた文章問題への回答を自動で生成するボットをクラウドに展開した ( (#sec_fargate_qabot)). タスクの投入に応じて動的に計算リソースが作成・削除される様子を実際に体験できただろう.

    さらに, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する では AWS Batch を用いてニューラルネットの学習を並列に実行する方法を紹介した. ここで紹介した方法は,ミニマムであるが,計算機システムを大規模化していくためのエッセンスが網羅されている. これらのハンズオン体験から,クラウド技術を応用してどのように現実世界の問題を解いていくのか,なんとなくイメージが伝わっただろうか?

    本書の第三部では,さらにレベルアップし,サーバーレスアーキテクチャという最新のクラウドの設計手法について解説する. その応用として,ハンズオンでは簡単な SNS サービスをゼロから実装する. 引き続きクラウドの最先端の世界を楽しんでいこう!

    + \ No newline at end of file diff --git a/development/aws/aws-get-started.html b/development/aws/aws-get-started.html index 704c7921..4d546bf5 100644 --- a/development/aws/aws-get-started.html +++ b/development/aws/aws-get-started.html @@ -5,17 +5,17 @@ AWS 入門 | Toshiki's Note - + - + - + - + @@ -38,156 +38,156 @@ -
    Skip to content

    AWS 入門

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:2.4k
    Reading:9 min

    AWS とは?

    本書では,クラウドの実践を行うプラットフォームとして, AWS を用いる. 実践にあたって,最低限必要な AWS の知識を本章では解説しよう.

    AWS (Amazon Web Services) は Amazon 社が提供する総合的なクラウドプラットフォームである. AWS は Amazon 社が持つ膨大な計算リソースを貸し出すクラウドサービスとして,2006 年に誕生した. 2021 年では,クラウドプロバイダーとして最大のマーケットシェア (約 32%) を保持している (参照). Netflix や Slack をはじめとした多くのウェブ関連のサービスで,一部または全てのサーバーリソースが AWS から提供されているとのことである. よって,知らないうちに AWS の恩恵にあずかっている人も少なくないはずだ.

    最大のシェアをもつだけに,機能・サービスの幅広さはほかのクラウドプラットフォームと比べ抜きんでている. また,利用者数が多いことを反映して,公式あるいはサードパーティによる技術紹介記事が数多くウェブ上に存在しているだけでなく,ライブラリのユーザーコミュニティも大きく問題解決が捗るのも魅力の一つだ. 初期のころウェブビジネスを行う企業がユーザーの大半を占めていたが,最近は大学などでの科学研究用途としても頻繁に用いられるようになってきている.

    AWS の機能・サービス

    figure_title は,執筆時点において AWS で提供されている主要な機能・サービスの一覧である.

    AWSで提供されている主要なサービス一覧

    計算,ストレージ,データベース,ネットワーク,セキュリティなど,クラウドの構築に必要な様々な要素が独立したコンポーネントとして提供されている. 基本的に,これらを組み合わせることで一つのクラウドシステムができあがる.

    また,機械学習・音声認識・AR/VR など,特定のアプリケーションにパッケージ済みのサービスも提供されている. これらを合計すると全部で 170 個以上のサービスが提供されているとのことである (参照).

    AWS の初心者が陥りがちなのは,大量のサービスの数に圧倒され,どこから手をつけたらよいのかわからなくなる,という状況である. たくさんのサービスの中から,どのサービスをどの順番で学んでいったらいいのか,その道筋すら明らかでなく,大きな参入障壁となっていることは間違いない. だが実のところ, AWS の基本的な構成要素はそのうちの数個のみに限られる. 基本要素となる機能の使い方を知れば, AWS のおおよそのリソースを使いこなすことが可能になる. ほかの機能の多くは,基本の要素を組み合わせて特定のアプリケーションに特化したパッケージとして AWS が用意したものである. そのポイントを認知することが, AWS の学習の最初のステップである.

    ここでは, AWS 上でクラウドシステムを構築するときの基本となる構成要素を列挙する. これらは後のハンズオンで実際にプログラムを書きながら体験する. 現時点では,名前だけでも頭の片隅に記憶してもらえればよい.

    計算

    S3 EC2 (Elastic Compute Cloud) 様々なスペックの仮想マシンを作成し,計算を実行することができる. クラウドの最も基本となる構成要素である. (#sec_first_ec2), (#sec_jupyter_and_deep_learning), (#sec_aws_batch) で詳しく触れる.

    S3 Lambda Function as a Service (FaaS) とよばれる,小さな計算をサーバーなしで実行するためのサービス. サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    ストレージ

    S3EBS (Elastic Block Store) EC2 に付与することのできる仮想データドライブ. いわゆる"普通の"(一般的な OS で使われている)ファイルシステムを思い浮かべてくれたらよい.

    S3

    S3 (Simple Storage Service) Object Storage とよばれる,API を使ってデータの読み書きを行う,いうなれば”クラウド・ネイティブ”なデータの格納システムである. サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    データベース

    S3

    DynamoDB NoSQL 型のデータベースサービス (知っている人は mongoDB などを思い浮かべたらよい). サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    ネットワーク

    S3 VPC(Virtual Private Cloud) AWS 上に仮想ネットワーク環境を作成し,仮想サーバー間の接続を定義したり,外部からのアクセスなどを管理する. EC2 は VPC の内部に配置されなければならない.

    API Gateway S3

    API のエンドポイントとバックエンドのサービス (Lambda など) を接続する際に用いる,リバースプロキシとしての役割を担う. (#sec_bashoutter) で詳しく解説する.

    Region と Availability Zone

    AWS を使用する際に知っておかなければならない重要な概念として, リージョン (Region)Availability Zone (AZ) がある (figure_title). 以下ではこの概念について簡単に記述する.

    AWSにおける Region と Availability Zones

    リージョン (Region) とは,おおまかに言うとデータセンターの所在地のことである. 執筆時点において, AWS は世界の 25 の国と地域でデータセンターを所有している. figure_title は執筆時点で利用できるリージョンの世界地図を示している. 日本では東京と大阪にデータセンターがある. 各リージョンには固有の ID がついており,例えば東京は ap-northeast-1, 米国オハイオ州は us-east-2,などと定義されている.

    Regions in AWS(出典: https://aws.amazon.com/about-aws/global-infrastructure/)

    AWS コンソールにログインすると,画面右上のメニューバーでリージョンを選択することができる(figure_title, 赤丸で囲った箇所). EC2, S3 などの AWS のリソースは,リージョンごとに完全に独立である. したがって,リソースを新たにデプロイする際,あるいはデプロイ済みのリソースを閲覧する際は,コンソールのリージョンが正しく設定されているか,確認する必要がある. ウェブビジネスを展開する場合などは,世界の各地にクラウドを展開する必要があるが,個人的な研究用途として用いる場合は,最寄りのリージョン (i.e. 東京) を使えば基本的に問題ない.

    AWSコンソールでリージョンを選択

    Avaialibity Zone (AZ) とは,リージョン内で地理的に隔離されたデータセンターのことである. それぞれのリージョンは 2 個以上の AZ を有しており,もし一つの AZ で火災や停電などが起きた場合でも,ほかの AZ がその障害をカバーすることができる. また, AZ 間は高速な AWS 専用ネットワーク回線で結ばれているため, AZ 間のデータ転送は極めて早い. AZ は,ビジネスなどでサーバーダウンが許容されない場合などに注意すべき概念であり,個人的な用途で使う限りにおいてはあまり深く考慮する必要はない.言葉の意味だけ知っておけば十分である.

    AWS を使用する際,どこのリージョンを指定するのがよいのだろうか? インターネットの接続速度の観点からは,地理的に一番近いリージョンを使用するのが一般的によいだろう. 一方, EC2 の利用料などはリージョンごとに価格設定が若干 (10-20%程度) 異なる. したがって,自分が最も頻繁に利用するサービスの価格が最も安く設定されているリージョンを選択する,というのも重要な視点である. また,いくつかのサービスは,特定のリージョンで利用できない場合もある. これらのポイントから総合的に判断して使用するリージョンを決めると良い.

    AWS Educate を利用している読者へ

    執筆時点において,AWS Educate による Starter Account を使用している場合は us-east-1 region のみ利用できる (参照).

    AWS でのクラウド開発

    AWS のクラウドの全体像がわかってきたところで,次のトピックとして,どのようにして AWS 上にクラウドの開発を行い,展開していくかについての概略を解説しよう.

    AWS のリソースを追加・編集・削除するなどの操作を実行するには,コンソールを用いる方法と,API を用いる方法の,二つの経路がある.

    コンソール画面からリソースを操作する

    AWS のアカウントにログインすると,まず最初に表示されるのがAWS コンソールである (figure_title).

    AWSマネージメントコンソール画面

    コンソールを使うことで, EC2 のインスタンスを立ち上げたり,S3 のデータを追加・削除したり,ログを閲覧したりなど,AWS 上のあらゆるリソースの操作を GUI (Graphical User Interface) を通して実行することができる. 初めて触る機能をポチポチと試したり,デバッグを行うときなどにとても便利である

    コンソールはさらっと機能を試したり,開発中のクラウドのデバッグをするときには便利なのであるが,実際にクラウドの開発をする場面でこれを直接いじることはあまりない. むしろ,次に紹介する API を使用して,プログラムとしてクラウドのリソースを記述することで開発を行うのが一般的である. そのような理由で,本書では AWS コンソールを使った AWS の使い方はあまり触れない. AWS のドキュメンテーションには,たくさんの チュートリアル が用意されており,コンソール画面から様々な操作を行う方法が記述されているので,興味がある読者はそちらを参照されたい.

    API からリソースを操作する

    API (Application Programming Interface) を使うことで,コマンドを AWS に送信し,クラウドのリソースの操作をすることができる. API とは,端的に言えば AWS が公開しているコマンドの一覧であり,GET, POST, DELETE などの REST API から構成されている (REST API については (#sec_rest_api) で簡単に解説する). が,直接 REST API を入力するのは面倒であるので,その手間を解消するための様々なツールが提供されている.

    例えば, AWS CLI は, UNIX コンソールから AWS API を実行するための CLI (Command Line Interface) である. CLI に加えて,いろいろなプログラミング言語での SDK (Software Development Kit) が提供されている.以下に一例を挙げる.

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    python
    import boto3
    +    
    Skip to content

    AWS 入門

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:2.4k
    Reading:9 min

    AWS とは?

    本書では,クラウドの実践を行うプラットフォームとして, AWS を用いる. 実践にあたって,最低限必要な AWS の知識を本章では解説しよう.

    AWS (Amazon Web Services) は Amazon 社が提供する総合的なクラウドプラットフォームである. AWS は Amazon 社が持つ膨大な計算リソースを貸し出すクラウドサービスとして,2006 年に誕生した. 2021 年では,クラウドプロバイダーとして最大のマーケットシェア (約 32%) を保持している (参照). Netflix や Slack をはじめとした多くのウェブ関連のサービスで,一部または全てのサーバーリソースが AWS から提供されているとのことである. よって,知らないうちに AWS の恩恵にあずかっている人も少なくないはずだ.

    最大のシェアをもつだけに,機能・サービスの幅広さはほかのクラウドプラットフォームと比べ抜きんでている. また,利用者数が多いことを反映して,公式あるいはサードパーティによる技術紹介記事が数多くウェブ上に存在しているだけでなく,ライブラリのユーザーコミュニティも大きく問題解決が捗るのも魅力の一つだ. 初期のころウェブビジネスを行う企業がユーザーの大半を占めていたが,最近は大学などでの科学研究用途としても頻繁に用いられるようになってきている.

    AWS の機能・サービス

    figure_title は,執筆時点において AWS で提供されている主要な機能・サービスの一覧である.

    AWSで提供されている主要なサービス一覧

    計算,ストレージ,データベース,ネットワーク,セキュリティなど,クラウドの構築に必要な様々な要素が独立したコンポーネントとして提供されている. 基本的に,これらを組み合わせることで一つのクラウドシステムができあがる.

    また,機械学習・音声認識・AR/VR など,特定のアプリケーションにパッケージ済みのサービスも提供されている. これらを合計すると全部で 170 個以上のサービスが提供されているとのことである (参照).

    AWS の初心者が陥りがちなのは,大量のサービスの数に圧倒され,どこから手をつけたらよいのかわからなくなる,という状況である. たくさんのサービスの中から,どのサービスをどの順番で学んでいったらいいのか,その道筋すら明らかでなく,大きな参入障壁となっていることは間違いない. だが実のところ, AWS の基本的な構成要素はそのうちの数個のみに限られる. 基本要素となる機能の使い方を知れば, AWS のおおよそのリソースを使いこなすことが可能になる. ほかの機能の多くは,基本の要素を組み合わせて特定のアプリケーションに特化したパッケージとして AWS が用意したものである. そのポイントを認知することが, AWS の学習の最初のステップである.

    ここでは, AWS 上でクラウドシステムを構築するときの基本となる構成要素を列挙する. これらは後のハンズオンで実際にプログラムを書きながら体験する. 現時点では,名前だけでも頭の片隅に記憶してもらえればよい.

    計算

    S3 EC2 (Elastic Compute Cloud) 様々なスペックの仮想マシンを作成し,計算を実行することができる. クラウドの最も基本となる構成要素である. (#sec_first_ec2), (#sec_jupyter_and_deep_learning), (#sec_aws_batch) で詳しく触れる.

    S3 Lambda Function as a Service (FaaS) とよばれる,小さな計算をサーバーなしで実行するためのサービス. サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    ストレージ

    S3EBS (Elastic Block Store) EC2 に付与することのできる仮想データドライブ. いわゆる"普通の"(一般的な OS で使われている)ファイルシステムを思い浮かべてくれたらよい.

    S3

    S3 (Simple Storage Service) Object Storage とよばれる,API を使ってデータの読み書きを行う,いうなれば”クラウド・ネイティブ”なデータの格納システムである. サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    データベース

    S3

    DynamoDB NoSQL 型のデータベースサービス (知っている人は mongoDB などを思い浮かべたらよい). サーバーレスアーキテクチャの章 ( (#sec_serverless)) で詳しく解説する.

    ネットワーク

    S3 VPC(Virtual Private Cloud) AWS 上に仮想ネットワーク環境を作成し,仮想サーバー間の接続を定義したり,外部からのアクセスなどを管理する. EC2 は VPC の内部に配置されなければならない.

    API Gateway S3

    API のエンドポイントとバックエンドのサービス (Lambda など) を接続する際に用いる,リバースプロキシとしての役割を担う. (#sec_bashoutter) で詳しく解説する.

    Region と Availability Zone

    AWS を使用する際に知っておかなければならない重要な概念として, リージョン (Region)Availability Zone (AZ) がある (figure_title). 以下ではこの概念について簡単に記述する.

    AWSにおける Region と Availability Zones

    リージョン (Region) とは,おおまかに言うとデータセンターの所在地のことである. 執筆時点において, AWS は世界の 25 の国と地域でデータセンターを所有している. figure_title は執筆時点で利用できるリージョンの世界地図を示している. 日本では東京と大阪にデータセンターがある. 各リージョンには固有の ID がついており,例えば東京は ap-northeast-1, 米国オハイオ州は us-east-2,などと定義されている.

    Regions in AWS(出典: https://aws.amazon.com/about-aws/global-infrastructure/)

    AWS コンソールにログインすると,画面右上のメニューバーでリージョンを選択することができる(figure_title, 赤丸で囲った箇所). EC2, S3 などの AWS のリソースは,リージョンごとに完全に独立である. したがって,リソースを新たにデプロイする際,あるいはデプロイ済みのリソースを閲覧する際は,コンソールのリージョンが正しく設定されているか,確認する必要がある. ウェブビジネスを展開する場合などは,世界の各地にクラウドを展開する必要があるが,個人的な研究用途として用いる場合は,最寄りのリージョン (i.e. 東京) を使えば基本的に問題ない.

    AWSコンソールでリージョンを選択

    Avaialibity Zone (AZ) とは,リージョン内で地理的に隔離されたデータセンターのことである. それぞれのリージョンは 2 個以上の AZ を有しており,もし一つの AZ で火災や停電などが起きた場合でも,ほかの AZ がその障害をカバーすることができる. また, AZ 間は高速な AWS 専用ネットワーク回線で結ばれているため, AZ 間のデータ転送は極めて早い. AZ は,ビジネスなどでサーバーダウンが許容されない場合などに注意すべき概念であり,個人的な用途で使う限りにおいてはあまり深く考慮する必要はない.言葉の意味だけ知っておけば十分である.

    AWS を使用する際,どこのリージョンを指定するのがよいのだろうか? インターネットの接続速度の観点からは,地理的に一番近いリージョンを使用するのが一般的によいだろう. 一方, EC2 の利用料などはリージョンごとに価格設定が若干 (10-20%程度) 異なる. したがって,自分が最も頻繁に利用するサービスの価格が最も安く設定されているリージョンを選択する,というのも重要な視点である. また,いくつかのサービスは,特定のリージョンで利用できない場合もある. これらのポイントから総合的に判断して使用するリージョンを決めると良い.

    AWS Educate を利用している読者へ

    執筆時点において,AWS Educate による Starter Account を使用している場合は us-east-1 region のみ利用できる (参照).

    AWS でのクラウド開発

    AWS のクラウドの全体像がわかってきたところで,次のトピックとして,どのようにして AWS 上にクラウドの開発を行い,展開していくかについての概略を解説しよう.

    AWS のリソースを追加・編集・削除するなどの操作を実行するには,コンソールを用いる方法と,API を用いる方法の,二つの経路がある.

    コンソール画面からリソースを操作する

    AWS のアカウントにログインすると,まず最初に表示されるのがAWS コンソールである (figure_title).

    AWSマネージメントコンソール画面

    コンソールを使うことで, EC2 のインスタンスを立ち上げたり,S3 のデータを追加・削除したり,ログを閲覧したりなど,AWS 上のあらゆるリソースの操作を GUI (Graphical User Interface) を通して実行することができる. 初めて触る機能をポチポチと試したり,デバッグを行うときなどにとても便利である

    コンソールはさらっと機能を試したり,開発中のクラウドのデバッグをするときには便利なのであるが,実際にクラウドの開発をする場面でこれを直接いじることはあまりない. むしろ,次に紹介する API を使用して,プログラムとしてクラウドのリソースを記述することで開発を行うのが一般的である. そのような理由で,本書では AWS コンソールを使った AWS の使い方はあまり触れない. AWS のドキュメンテーションには,たくさんの チュートリアル が用意されており,コンソール画面から様々な操作を行う方法が記述されているので,興味がある読者はそちらを参照されたい.

    API からリソースを操作する

    API (Application Programming Interface) を使うことで,コマンドを AWS に送信し,クラウドのリソースの操作をすることができる. API とは,端的に言えば AWS が公開しているコマンドの一覧であり,GET, POST, DELETE などの REST API から構成されている (REST API については (#sec_rest_api) で簡単に解説する). が,直接 REST API を入力するのは面倒であるので,その手間を解消するための様々なツールが提供されている.

    例えば, AWS CLI は, UNIX コンソールから AWS API を実行するための CLI (Command Line Interface) である. CLI に加えて,いろいろなプログラミング言語での SDK (Software Development Kit) が提供されている.以下に一例を挙げる.

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    python
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン ( (#sec_first_ec2)) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    python
    import boto3
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン ( (#sec_first_ec2)) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    python
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    import boto3
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    AWS CLI のインストールについては, (#aws_cli_install) を参照.

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは (#aws_cli_install) を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    sh
    $ aws s3 ls
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    AWS CLI のインストールについては, (#aws_cli_install) を参照.

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは (#aws_cli_install) を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    sh
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    sh
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    sh
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    AWS 上のあらゆるリソースには, Amazon Resource Name (ARN) という固有の ID が付与されている. ARN は arn:aws:s3:::my_bucket/ のようなフォーマットで記述され,ARN を使用することで,特定の AWS リソース (S3 のバケットや EC2 のインスタンス) を一意的に参照することができる.

    S3 バケットや EC2 インスタンスなどには ARN に加えて,人間が読みやすい名前を定義することも可能である. この場合は,ARN または名前のどちらを用いても同じリソースを参照することが可能である.

    CloudFormation と AWS CDK

    CloudFormation による Infrastructure as Code (IaC)

    前節で述べたように,AWS API を使うことでクラウドのあらゆるリソースの作成・管理が可能である. よって,原理上は, API のコマンドを組み合わせていくことで,自分の作りたいクラウドを設計することができる.

    しかし,ここで実用上考慮しなければならない点が一つある. AWS API には大きく分けて,リソースを操作するコマンドと,タスクを実行するコマンドがあることである (figure_title).

    AWS APIはリソースを操作するコマンドとタスクを実行するコマンドに大きく分けられる.リソースを記述・管理するのに使われるのが, CloudFormation と CDK である.

    リソースを操作するとは,EC2 のインスタンスを起動したり,S3 のバケットを作成したり,データベースに新たなテーブルを追加する,などの静的なリソースを準備する 操作を指す. "ハコ"を作る操作とよんでも良いだろう. このようなコマンドは,クラウドのデプロイ時にのみ,一度だけ実行されればよい

    タスクを実行するコマンド とは, EC2 のインスタンスにジョブを投入したり, S3 のバケットにデータを読み書きするなどの操作を指す. これは, EC2 や S3 などのリソース ("ハコ") を前提として,その内部で実行されるべき計算を記述するものである. 前者に比べてこちらは動的な操作を担当する,と捉えることもできる.

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    json
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +2020-06-07 23:54:19   13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    AWS 上のあらゆるリソースには, Amazon Resource Name (ARN) という固有の ID が付与されている. ARN は arn:aws:s3:::my_bucket/ のようなフォーマットで記述され,ARN を使用することで,特定の AWS リソース (S3 のバケットや EC2 のインスタンス) を一意的に参照することができる.

    S3 バケットや EC2 インスタンスなどには ARN に加えて,人間が読みやすい名前を定義することも可能である. この場合は,ARN または名前のどちらを用いても同じリソースを参照することが可能である.

    CloudFormation と AWS CDK

    CloudFormation による Infrastructure as Code (IaC)

    前節で述べたように,AWS API を使うことでクラウドのあらゆるリソースの作成・管理が可能である. よって,原理上は, API のコマンドを組み合わせていくことで,自分の作りたいクラウドを設計することができる.

    しかし,ここで実用上考慮しなければならない点が一つある. AWS API には大きく分けて,リソースを操作するコマンドと,タスクを実行するコマンドがあることである (figure_title).

    AWS APIはリソースを操作するコマンドとタスクを実行するコマンドに大きく分けられる.リソースを記述・管理するのに使われるのが, CloudFormation と CDK である.

    リソースを操作するとは,EC2 のインスタンスを起動したり,S3 のバケットを作成したり,データベースに新たなテーブルを追加する,などの静的なリソースを準備する 操作を指す. "ハコ"を作る操作とよんでも良いだろう. このようなコマンドは,クラウドのデプロイ時にのみ,一度だけ実行されればよい

    タスクを実行するコマンド とは, EC2 のインスタンスにジョブを投入したり, S3 のバケットにデータを読み書きするなどの操作を指す. これは, EC2 や S3 などのリソース ("ハコ") を前提として,その内部で実行されるべき計算を記述するものである. 前者に比べてこちらは動的な操作を担当する,と捉えることもできる.

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    json
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    python
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    python
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

    • AWS CDK Examples: CDK を使ったプロジェクトの例が多数紹介されている. ここにある例をテンプレートに自分のアプリケーションの開発を進めるとよい.
    - + host = ec2.Instance( + self, "MyGreatEc2", + instance_type=ec2.InstanceType("t2.micro"), + machine_image=ec2.MachineImage.latest_amazon_linux(), + vpc=vpc, + ... + )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

    • AWS CDK Examples: CDK を使ったプロジェクトの例が多数紹介されている. ここにある例をテンプレートに自分のアプリケーションの開発を進めるとよい.
    + \ No newline at end of file diff --git a/development/aws/closing.html b/development/aws/closing.html index 20044142..3c8c064a 100644 --- a/development/aws/closing.html +++ b/development/aws/closing.html @@ -5,15 +5,15 @@ まとめ | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ - - + + \ No newline at end of file diff --git a/development/aws/cloud.html b/development/aws/cloud.html index 7135c6b8..a2081ff0 100644 --- a/development/aws/cloud.html +++ b/development/aws/cloud.html @@ -5,16 +5,16 @@ クラウド概論 | Toshiki's Note - + - + - + - + @@ -37,8 +37,8 @@ -
    Skip to content

    クラウド概論

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:1.5k
    Reading:4 min

    クラウドとは?

    Cloud

    クラウドとはなにか? クラウドという言葉は,それ自身がとても広い意味をもつので,厳密な定義付けを行うことは難しい.

    学術的な意味でのクラウドの定義づけをするとしたら,NIST(米国・国立標準技術研究所) による The NIST Definition of Cloud Computing が引用されることが多い. ここに記載されたクラウドの定義・モデルを図示したのが figure_title である.

    The NIST Definition of Cloud Computing

    これによると,クラウドとは以下の要件が満たされたハードウェア/ソフトウェアの総体のことをいう.

    • On-demand self-service 利用者のリクエストに応じて計算資源が自動的に割り当てられる.

    • Broad network access 利用者はネットワークを通じてクラウドにアクセスできる.

    • Resource pooling クラウドプロバイダーは,所有する計算資源を分割することで複数の利用者に計算資源を割り当てる.

    • Rapid elasticity 利用者のリクエストに応じて,迅速に計算資源の拡大あるいは縮小を行うことができる.

    • Measured service 計算資源の利用量を計測・監視することができる.

    …と,いわれても抽象的でよくわからないかもしれない.もう少し具体的な話をする.

    個人が所有する計算機で, CPU をアップグレードしようと思ったら,物理的に筐体を開け,CPU ソケットを露出させ,新しい CPU に交換する必要があるだろう. あるいは,ストレージがいっぱいになってしまったら,古いディスクを抜き取り,新しいディスクを挿入する必要がある. 計算機の場所を移動させたときには,新しい部屋の LAN ケーブルを差し込まないとネットワークには接続できない.

    クラウドでは,これらの操作がプログラムからのコマンドによって実行できる. CPU が 1000 個欲しいと思ったならば,そのようにクラウドプロバイダーにリクエストを送れば良い. すると,数分もしないうちに 1000 CPU の計算資源が割り当てられる. ストレージを 1TB から 10TB に拡張しようと思ったならば,そのようにコマンドを送ればよい (これは,Google Drive や Dropbox などのサービスなどで馴染みのある人も多いだろう). 計算資源を使い終わったら,そのことをプロバイダーに伝えれば,割り当て分はすぐさま削除される. クラウドプロバイダーは,使った計算資源の量を正確にモニタリングしており,その量をもとに利用料金の計算が行われる.

    このように,クラウドの本質は物理的なハードウェアの仮想化・抽象化であり,利用者はコマンドを通じて,まるでソフトウェアの一部かのように,物理的なハードウェアの管理・運用を行うことができる. もちろん,背後では,データセンターに置かれた膨大な数の計算機が大量の電力を消費しながら稼働している. クラウドプロバイダーはデータセンターの計算資源を上手にやりくりし,ソフトウェアとしてのインターフェースをユーザーに提供することで,このような仮想化・抽象化を達成しているわけである. クラウドプロバイダーの視点からすると,大勢のユーザーに計算機を貸し出し,データセンターの稼働率を常時 100%に近づけることで,利益率の最大化を図っているのである.

    著者の言葉で,クラウドの重要な特性を定義するならば,以下のようになる.

    クラウドとは計算機ハードウェアの抽象化である.つまり,物理的なハードウェアをソフトウェアの一部かのように自在に操作・拡大・接続することを可能にする技術である.

    先述の The NIST Definition of Cloud Computing に戻ると,クラウドプロバイダーによるクラウドサービスの形態としては,次の三つが定義されている (figure_title).

    • Software as a Service (SaaS): クラウド上で実行されるアプリケーションをサービスとして利用者に提供する形態. 例として, Google Drive や Slack などが挙げられる. 利用者は,背後にあるクラウドのインフラ (ネットワークやサーバーなど) には直接触れず,アプリケーションとして提供されているクラウドサービスを享受する.

    • Platform as a Service (PaaS): 顧客の作成したアプリケーション (多くの場合データベースと API リクエスト処理を行うサーバーのコードから構成される) をデプロイする環境をサービスとして利用者に提供する形態. PaaS では利用者はクラウドのインフラに直接触れることはなく,計算負荷が増減した際のサーバーのスケーリングはクラウドプロバイダーによってなされる. 例としては, Google App Engine や Heroku などがある.

    • Infrastructure as a Service (IaaS): クラウド上の計算インフラストラクチャーを従量課金制で利用者に提供する形態. 利用者は必要なネットワーク・サーバー・ストレージをプロバイダーから借り受け,そこに自身のアプリケーションを展開し運用する. IaaS の例としては AWS EC2 などが挙げられる.

    本書が扱うのは,主に IaaS におけるクラウド開発である. すなわち,開発者がクラウドのインフラを直接操作し,所望のネットワーク・サーバー・ストレージなどを一から構成し,そこにアプリケーションを展開するというクラウド開発である. この意味において,クラウドの開発とはクラウドインフラストラクチャーを定義・展開するプログラムを構築するステップインフラ上で実際に走るアプリケーションを作成するステップの二つに分けることができる. この二つは,プログラマーの技術としてはある程度分業を行うことが可能であるが,最も効率化・最適化されたクラウドシステムを構築するためには両方の理解が必須である. 本書では,前者 (クラウドインフラの記述) に重きを置きつつ,アプリケーションレイヤーの話題も取り扱う. PaaS とは,開発者はアプリケーションレイヤーの開発に注力し,クラウドインフラの部分はクラウドプロバイダーに依存するという概念である. PaaS は,クラウドインフラの開発が不要になることで開発の時間が短縮されるが,細かなインフラの挙動はコントロールできないという限界がある. 本書では PaaS についてはとくに取り扱わない.

    SaaS は本書の文脈では開発による"成果物"と捉えられるだろう. すなわち, IaaS を構成するプログラムを作成し展開することによって,一般の人が利用できるようなウェブ上の計算サービスやデータベースを提供することが開発の最終ゴールである. 本書のハンズオンではその実例として,シンプルな SNS の作成 ( (#sec_bashoutter)) などの演習を提供する.

    なお,最近では Function as a Service (FaaS) やサーバーレスコンピューティングなども新たなクラウドのカテゴリとして認知されている. これらの概念については (#sec_intro_serverless) などの章で詳しく触れていく. 本書を読み進める中で明らかになるように,クラウドの技術は日進月歩である. 本書では実用的・教育的な観点から,従来的なクラウドの設計概念に触れたあと,サーバーレスなどの最新の技術も網羅するので,楽しみにしながら読み進めていただきたい.

    最後に,The NIST Definition of Cloud Computing によると,クラウドの運用形態について次のような定義がなされている (figure_title). 特定の組織・団体・企業の内部のみで使用されるクラウドを,プライベートクラウド (private cloud) とよぶ. 例えば,大学や研究機関では,その機関の構成員向けの大規模計算機サーバーが運用されていることが多い. プライベートクラウドは,組織の構成員ならば無料もしくは極めて割安のコストで計算を実行できる. しかし,使用できる計算資源の上限は限られる場合が多く,拡張時の柔軟性に欠ける場合もある.

    一方,商用のサービスとして一般の顧客に向けたクラウドのことを,パブリッククラウド (public cloud) とよぶ. 有名なパブリッククラウドプラットフォームの例を挙げると, Google 社が提供する Google Cloud Platform (GCP), Microsoft 社が提供する Azure, Amazon 社が提供する Amazon Web Services (AWS) などがある. パブリッククラウドを利用する場合は,プロバイダーの設定した利用料金を支払うことになる. その分,巨大なデータセンターを運用する企業の計算資源にアクセスすることができるので,計算のキャパシティは無尽蔵にあるといって過言でない.

    第三のクラウドの運用形態として,コミュニティクラウド (community cloud) が挙げられる. これは,例えば政府の省庁・機関など目的・役割を共有する団体・組織が共有して運用するクラウドを指す. 最後に,ハイブリッドクラウド (hybrid cloud) という形態もあり,これはプライベート・パブリック・コミュニティクラウドの二つ以上の組み合わせによって構成されるクラウドのことである. データ保護の観点から,いくつかの機密データやプライバシーに関わる情報はプライベートクラウドに保持し,残りのシステムをパブリッククラウドに依存する,などの形態が想定される.

    本書で説明するのは,基本的にパブリッククラウドを使ったクラウド開発である. 特に,Amazon Web Services (AWS) を使用して,具体的な技術と概念を学んでいく. 一方で,サーバーのスケーリングや仮想計算環境などのテクニックはすべてのクラウドに共通な概念であるので,クラウドのプラットフォームが変わろうと一般に通用する知識も同時に身につくはずだ.

    なぜクラウドを使うのか?

    上述のように,クラウドとはプログラムを通じて自由に計算資源を操作することのできる計算環境である. ここでは,リアルなローカル計算環境と比べて,なぜクラウドを使うと良いことがあるのかについて述べたい.

    1. 自由にサーバーのサイズをスケールできる

      なにか新しいプロジェクトを始めるとき,あらかじめ必要なサーバーのスペックを知るのは難しい. いきなり大きなサーバーを買うのはリスクが高い. 一方で,小さすぎるサーバーでは,後のアップグレードが面倒である. クラウドを利用すれば,プロジェクトを進めながら,必要な分だけの計算資源を確保することができる. 2. 自分でサーバーをメンテナンスする必要がない

      悲しいことに,コンピュータとは古くなるものである.最近の技術の進歩の速度からすると,5 年も経てば,もはや当時の最新コンピュータも化石と同じである. 5 年ごとにサーバーを入れ替えるのは相当な手間である. またサーバーの停電や故障など不意の障害への対応も必要である. クラウドでは,そのようなインフラの整備やメンテナンスはプロバイダーが自動でやってくれるので,ユーザーが心配する必要がない. 3. 初期コスト 0

      自前の計算環境とクラウドの,経済的なコストのイメージを示したのが figure_title である. クラウドを利用する場合の初期コストは基本的に 0 である. その後,使った利用量に応じてコストが増大していく. 一方,自前の計算環境では,大きな初期コストが生じる. その分,初期投資後のコストの増加は,電気利用料やサーバー維持費などに留まるため,クラウドを利用した場合よりも傾きは小さくなる. 自前の計算機では,ある一定期間後,サーバーのアップグレードなどによる支出が生じることがある. 一方,クラウドを利用する場合は,そのような非連続なコストの増大は基本的に生じない. クラウドのコストのカーブが,自前計算環境のコストのカーブの下にある範囲においては,クラウドを使うことは経済的なコスト削減につながる.

      クラウドと自前計算機環境の経済的コストの比較

    とくに,**1.**の点は研究の場面では重要であると筆者は感じる. 研究をやっていて,四六時中計算を走らせ続けるという場合は少ない. むしろ,新しいアルゴリズムが完成したとき・新しいデータが届いたとき,集中的・突発的に計算タスクが増大することが多いだろう. そういったときに,フレキシブルに計算力を増強させることができるのは,クラウドを使う大きなメリットである.

    ここまでクラウドを使うメリットを述べたが,逆に,デメリットというのも当然存在する.

    1. クラウドは賢く使わないといけない

      figure_title で示したコストのカーブにあるとおり,使い方によっては自前の計算環境のほうがコスト的に有利な場面は存在しうる. クラウドを利用する際は,使い終わった計算資源はすぐに削除するなど,利用者が賢く管理を行う必要があり,これを怠ると思いもしない額の請求が届く可能性がある. 2. セキュリティ

      クラウドは,インターネットを通じて世界のどこからでもアクセスできる状態にあり,セキュリティ管理を怠ると簡単にハッキングの対象となりうる. ハッキングを受けると,情報流出だけでなく,経済的な損失を被る可能性がある. 3. ラーニングカーブ

      上記のように,コスト・セキュリティなど,クラウドを利用する際に留意しなければならない点は多い. 賢くクラウドを使うには,十分なクラウドの理解が必要であり,そのラーニングカーブを乗り越える必要がある.

    Mac/Linux などでコマンドを入力するときに使用する,あの黒い画面のことを Terminal とよんだりする. この言葉の語源をご存知だろうか?

    Terminal

    この言葉の語源は,コンピュータが誕生して間もない頃の時代に遡る. その頃のコンピュータというと,何千何万のという数の真空管が接続された,会議室一個分くらいのサイズのマシンであった. そのような高価でメンテが大変な機材であるから,当然みんなでシェアして使うことが前提となる. ユーザーがコンピュータにアクセスするため,マシンからは何本かのケーブルが伸び,それぞれにキーボードとスクリーンが接続されていた… これを Terminal とよんでいたのである. 人々は,代わる代わる Terminal の前に座って,計算機との対話を行っていた.

    時代は流れ,Windows や Mac などのいわゆるパーソナルコンピュータの出現により,コンピュータはみんなで共有するものではなく,個人が所有するものになった.

    最近のクラウドの台頭は,みんなで大きなコンピュータをシェアするという,最初のコンピュータの使われ方に原点回帰していると捉えることもできる. 一方で,スマートフォンやウェアラブルなどのエッジデバイスの普及も盛んであり,個人が複数の"小さな"コンピュータを所有する,という流れも同時に進行しているのである.

    - +
    Skip to content

    クラウド概論

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:1.5k
    Reading:4 min

    クラウドとは?

    Cloud

    クラウドとはなにか? クラウドという言葉は,それ自身がとても広い意味をもつので,厳密な定義付けを行うことは難しい.

    学術的な意味でのクラウドの定義づけをするとしたら,NIST(米国・国立標準技術研究所) による The NIST Definition of Cloud Computing が引用されることが多い. ここに記載されたクラウドの定義・モデルを図示したのが figure_title である.

    The NIST Definition of Cloud Computing

    これによると,クラウドとは以下の要件が満たされたハードウェア/ソフトウェアの総体のことをいう.

    • On-demand self-service 利用者のリクエストに応じて計算資源が自動的に割り当てられる.

    • Broad network access 利用者はネットワークを通じてクラウドにアクセスできる.

    • Resource pooling クラウドプロバイダーは,所有する計算資源を分割することで複数の利用者に計算資源を割り当てる.

    • Rapid elasticity 利用者のリクエストに応じて,迅速に計算資源の拡大あるいは縮小を行うことができる.

    • Measured service 計算資源の利用量を計測・監視することができる.

    …と,いわれても抽象的でよくわからないかもしれない.もう少し具体的な話をする.

    個人が所有する計算機で, CPU をアップグレードしようと思ったら,物理的に筐体を開け,CPU ソケットを露出させ,新しい CPU に交換する必要があるだろう. あるいは,ストレージがいっぱいになってしまったら,古いディスクを抜き取り,新しいディスクを挿入する必要がある. 計算機の場所を移動させたときには,新しい部屋の LAN ケーブルを差し込まないとネットワークには接続できない.

    クラウドでは,これらの操作がプログラムからのコマンドによって実行できる. CPU が 1000 個欲しいと思ったならば,そのようにクラウドプロバイダーにリクエストを送れば良い. すると,数分もしないうちに 1000 CPU の計算資源が割り当てられる. ストレージを 1TB から 10TB に拡張しようと思ったならば,そのようにコマンドを送ればよい (これは,Google Drive や Dropbox などのサービスなどで馴染みのある人も多いだろう). 計算資源を使い終わったら,そのことをプロバイダーに伝えれば,割り当て分はすぐさま削除される. クラウドプロバイダーは,使った計算資源の量を正確にモニタリングしており,その量をもとに利用料金の計算が行われる.

    このように,クラウドの本質は物理的なハードウェアの仮想化・抽象化であり,利用者はコマンドを通じて,まるでソフトウェアの一部かのように,物理的なハードウェアの管理・運用を行うことができる. もちろん,背後では,データセンターに置かれた膨大な数の計算機が大量の電力を消費しながら稼働している. クラウドプロバイダーはデータセンターの計算資源を上手にやりくりし,ソフトウェアとしてのインターフェースをユーザーに提供することで,このような仮想化・抽象化を達成しているわけである. クラウドプロバイダーの視点からすると,大勢のユーザーに計算機を貸し出し,データセンターの稼働率を常時 100%に近づけることで,利益率の最大化を図っているのである.

    著者の言葉で,クラウドの重要な特性を定義するならば,以下のようになる.

    クラウドとは計算機ハードウェアの抽象化である.つまり,物理的なハードウェアをソフトウェアの一部かのように自在に操作・拡大・接続することを可能にする技術である.

    先述の The NIST Definition of Cloud Computing に戻ると,クラウドプロバイダーによるクラウドサービスの形態としては,次の三つが定義されている (figure_title).

    • Software as a Service (SaaS): クラウド上で実行されるアプリケーションをサービスとして利用者に提供する形態. 例として, Google Drive や Slack などが挙げられる. 利用者は,背後にあるクラウドのインフラ (ネットワークやサーバーなど) には直接触れず,アプリケーションとして提供されているクラウドサービスを享受する.

    • Platform as a Service (PaaS): 顧客の作成したアプリケーション (多くの場合データベースと API リクエスト処理を行うサーバーのコードから構成される) をデプロイする環境をサービスとして利用者に提供する形態. PaaS では利用者はクラウドのインフラに直接触れることはなく,計算負荷が増減した際のサーバーのスケーリングはクラウドプロバイダーによってなされる. 例としては, Google App Engine や Heroku などがある.

    • Infrastructure as a Service (IaaS): クラウド上の計算インフラストラクチャーを従量課金制で利用者に提供する形態. 利用者は必要なネットワーク・サーバー・ストレージをプロバイダーから借り受け,そこに自身のアプリケーションを展開し運用する. IaaS の例としては AWS EC2 などが挙げられる.

    本書が扱うのは,主に IaaS におけるクラウド開発である. すなわち,開発者がクラウドのインフラを直接操作し,所望のネットワーク・サーバー・ストレージなどを一から構成し,そこにアプリケーションを展開するというクラウド開発である. この意味において,クラウドの開発とはクラウドインフラストラクチャーを定義・展開するプログラムを構築するステップインフラ上で実際に走るアプリケーションを作成するステップの二つに分けることができる. この二つは,プログラマーの技術としてはある程度分業を行うことが可能であるが,最も効率化・最適化されたクラウドシステムを構築するためには両方の理解が必須である. 本書では,前者 (クラウドインフラの記述) に重きを置きつつ,アプリケーションレイヤーの話題も取り扱う. PaaS とは,開発者はアプリケーションレイヤーの開発に注力し,クラウドインフラの部分はクラウドプロバイダーに依存するという概念である. PaaS は,クラウドインフラの開発が不要になることで開発の時間が短縮されるが,細かなインフラの挙動はコントロールできないという限界がある. 本書では PaaS についてはとくに取り扱わない.

    SaaS は本書の文脈では開発による"成果物"と捉えられるだろう. すなわち, IaaS を構成するプログラムを作成し展開することによって,一般の人が利用できるようなウェブ上の計算サービスやデータベースを提供することが開発の最終ゴールである. 本書のハンズオンではその実例として,シンプルな SNS の作成 ( (#sec_bashoutter)) などの演習を提供する.

    なお,最近では Function as a Service (FaaS) やサーバーレスコンピューティングなども新たなクラウドのカテゴリとして認知されている. これらの概念については (#sec_intro_serverless) などの章で詳しく触れていく. 本書を読み進める中で明らかになるように,クラウドの技術は日進月歩である. 本書では実用的・教育的な観点から,従来的なクラウドの設計概念に触れたあと,サーバーレスなどの最新の技術も網羅するので,楽しみにしながら読み進めていただきたい.

    最後に,The NIST Definition of Cloud Computing によると,クラウドの運用形態について次のような定義がなされている (figure_title). 特定の組織・団体・企業の内部のみで使用されるクラウドを,プライベートクラウド (private cloud) とよぶ. 例えば,大学や研究機関では,その機関の構成員向けの大規模計算機サーバーが運用されていることが多い. プライベートクラウドは,組織の構成員ならば無料もしくは極めて割安のコストで計算を実行できる. しかし,使用できる計算資源の上限は限られる場合が多く,拡張時の柔軟性に欠ける場合もある.

    一方,商用のサービスとして一般の顧客に向けたクラウドのことを,パブリッククラウド (public cloud) とよぶ. 有名なパブリッククラウドプラットフォームの例を挙げると, Google 社が提供する Google Cloud Platform (GCP), Microsoft 社が提供する Azure, Amazon 社が提供する Amazon Web Services (AWS) などがある. パブリッククラウドを利用する場合は,プロバイダーの設定した利用料金を支払うことになる. その分,巨大なデータセンターを運用する企業の計算資源にアクセスすることができるので,計算のキャパシティは無尽蔵にあるといって過言でない.

    第三のクラウドの運用形態として,コミュニティクラウド (community cloud) が挙げられる. これは,例えば政府の省庁・機関など目的・役割を共有する団体・組織が共有して運用するクラウドを指す. 最後に,ハイブリッドクラウド (hybrid cloud) という形態もあり,これはプライベート・パブリック・コミュニティクラウドの二つ以上の組み合わせによって構成されるクラウドのことである. データ保護の観点から,いくつかの機密データやプライバシーに関わる情報はプライベートクラウドに保持し,残りのシステムをパブリッククラウドに依存する,などの形態が想定される.

    本書で説明するのは,基本的にパブリッククラウドを使ったクラウド開発である. 特に,Amazon Web Services (AWS) を使用して,具体的な技術と概念を学んでいく. 一方で,サーバーのスケーリングや仮想計算環境などのテクニックはすべてのクラウドに共通な概念であるので,クラウドのプラットフォームが変わろうと一般に通用する知識も同時に身につくはずだ.

    なぜクラウドを使うのか?

    上述のように,クラウドとはプログラムを通じて自由に計算資源を操作することのできる計算環境である. ここでは,リアルなローカル計算環境と比べて,なぜクラウドを使うと良いことがあるのかについて述べたい.

    1. 自由にサーバーのサイズをスケールできる

      なにか新しいプロジェクトを始めるとき,あらかじめ必要なサーバーのスペックを知るのは難しい. いきなり大きなサーバーを買うのはリスクが高い. 一方で,小さすぎるサーバーでは,後のアップグレードが面倒である. クラウドを利用すれば,プロジェクトを進めながら,必要な分だけの計算資源を確保することができる. 2. 自分でサーバーをメンテナンスする必要がない

      悲しいことに,コンピュータとは古くなるものである.最近の技術の進歩の速度からすると,5 年も経てば,もはや当時の最新コンピュータも化石と同じである. 5 年ごとにサーバーを入れ替えるのは相当な手間である. またサーバーの停電や故障など不意の障害への対応も必要である. クラウドでは,そのようなインフラの整備やメンテナンスはプロバイダーが自動でやってくれるので,ユーザーが心配する必要がない. 3. 初期コスト 0

      自前の計算環境とクラウドの,経済的なコストのイメージを示したのが figure_title である. クラウドを利用する場合の初期コストは基本的に 0 である. その後,使った利用量に応じてコストが増大していく. 一方,自前の計算環境では,大きな初期コストが生じる. その分,初期投資後のコストの増加は,電気利用料やサーバー維持費などに留まるため,クラウドを利用した場合よりも傾きは小さくなる. 自前の計算機では,ある一定期間後,サーバーのアップグレードなどによる支出が生じることがある. 一方,クラウドを利用する場合は,そのような非連続なコストの増大は基本的に生じない. クラウドのコストのカーブが,自前計算環境のコストのカーブの下にある範囲においては,クラウドを使うことは経済的なコスト削減につながる.

      クラウドと自前計算機環境の経済的コストの比較

    とくに,**1.**の点は研究の場面では重要であると筆者は感じる. 研究をやっていて,四六時中計算を走らせ続けるという場合は少ない. むしろ,新しいアルゴリズムが完成したとき・新しいデータが届いたとき,集中的・突発的に計算タスクが増大することが多いだろう. そういったときに,フレキシブルに計算力を増強させることができるのは,クラウドを使う大きなメリットである.

    ここまでクラウドを使うメリットを述べたが,逆に,デメリットというのも当然存在する.

    1. クラウドは賢く使わないといけない

      figure_title で示したコストのカーブにあるとおり,使い方によっては自前の計算環境のほうがコスト的に有利な場面は存在しうる. クラウドを利用する際は,使い終わった計算資源はすぐに削除するなど,利用者が賢く管理を行う必要があり,これを怠ると思いもしない額の請求が届く可能性がある. 2. セキュリティ

      クラウドは,インターネットを通じて世界のどこからでもアクセスできる状態にあり,セキュリティ管理を怠ると簡単にハッキングの対象となりうる. ハッキングを受けると,情報流出だけでなく,経済的な損失を被る可能性がある. 3. ラーニングカーブ

      上記のように,コスト・セキュリティなど,クラウドを利用する際に留意しなければならない点は多い. 賢くクラウドを使うには,十分なクラウドの理解が必要であり,そのラーニングカーブを乗り越える必要がある.

    Mac/Linux などでコマンドを入力するときに使用する,あの黒い画面のことを Terminal とよんだりする. この言葉の語源をご存知だろうか?

    Terminal

    この言葉の語源は,コンピュータが誕生して間もない頃の時代に遡る. その頃のコンピュータというと,何千何万のという数の真空管が接続された,会議室一個分くらいのサイズのマシンであった. そのような高価でメンテが大変な機材であるから,当然みんなでシェアして使うことが前提となる. ユーザーがコンピュータにアクセスするため,マシンからは何本かのケーブルが伸び,それぞれにキーボードとスクリーンが接続されていた… これを Terminal とよんでいたのである. 人々は,代わる代わる Terminal の前に座って,計算機との対話を行っていた.

    時代は流れ,Windows や Mac などのいわゆるパーソナルコンピュータの出現により,コンピュータはみんなで共有するものではなく,個人が所有するものになった.

    最近のクラウドの台頭は,みんなで大きなコンピュータをシェアするという,最初のコンピュータの使われ方に原点回帰していると捉えることもできる. 一方で,スマートフォンやウェアラブルなどのエッジデバイスの普及も盛んであり,個人が複数の"小さな"コンピュータを所有する,という流れも同時に進行しているのである.

    + \ No newline at end of file diff --git a/development/aws/docker-system.html b/development/aws/docker-system.html index eea4b99e..276cf408 100644 --- a/development/aws/docker-system.html +++ b/development/aws/docker-system.html @@ -5,16 +5,16 @@ Docker 入門 | Toshiki's Note - + - + - + - + @@ -37,72 +37,72 @@ -
    Skip to content

    Docker 入門

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:2.2k
    Reading:8 min

    ここまでの章で扱ってきたハンズオンでは,単一のサーバーを立ち上げ,それに SSH でログインをして,コマンドを叩くことで計算を行ってきた. いわば,パーソナルコンピュータの延長のような形でクラウドを使ってきたわけである. このような,インターネットのどこからでもアクセスできるパーソナルコンピュータとしてのクラウドという使い方も,もちろん便利であるし,いろいろな応用の可能性がある. しかし,これだけではクラウドの本当の価値は十分に発揮されていないと言うべきだろう. (#chap_cloud_basics) で述べたように,現代的なクラウドの一番の強みは自由に計算機の規模を拡大できることにある. すなわち,多数のサーバーを同時に起動し,複数のジョブを分散並列的に実行させることで大量のデータを処理してこそ,クラウドの本領が発揮されるのである.

    本章からはじまる 3 章分 (Docker 入門, (#sec_fargate_qabot), (#sec_aws_batch)) を使って,クラウドを利用することでどのように大規模な計算システムを構築しビッグデータの解析に立ち向かうのか,その片鱗をお見せしたい. とくに,前章で扱った深層学習をどのようにビッグデータに適用していくかという点に焦点を絞って議論していきたい. そのための前準備として,本章では Docker とよばれる計算機環境の仮想化ソフトウェアを紹介する (figure_title). 現代のクラウドは Docker なしには成り立たないといっても過言ではないだろう. クラウドに限らず,ローカルで行う計算処理にも Docker は大変便利である. AWS からは少し話が離れるが,しっかりと理解して前に進んでもらいたい.

    機械学習の大規模化

    先ほどから"計算システムの大規模化"と繰り返し唱えているが,それは具体的にはどのようなものを指しているのか? ここでは大規模データを処理するための計算機システムを,機械学習を例にとって見てみよう.

    (#sec_scientific_computing) で紹介した GPT-3 のような,超巨大な数のパラメータを有する深層学習モデルを学習させたいとしよう. そのような計算を行いたい場合,一つのサーバーでは計算力が到底足りない. したがって,典型的には figure_title に示すような計算システムの設計がなされる. すなわち,大量の教師データを小さなチャンクとして複数のマシンに分散し,並列的にニューラルネットのパラメータを最適化していくという構造である.

    複数の計算機を使った大規模な深層学習モデルの訓練

    あるいは,学習済みのモデルを大量のデータに適用し,解析を行いたいとしよう. たとえば, SNS のプラットフォームで大量の画像が与えられて,それぞれの写真に何が写っているのかをラベルづけする,などのアプリケーションを想定できる. そのような場合は, figure_title のようなアーキテクチャが考えられるだろう. すなわち,大量のデータを複数のマシンで分割し,それぞれのマシンで推論の計算を行うというような構造である.

    複数の計算機による深層学習モデルを使った推論計算

    このような複数の計算機を同時に走らせるようなアプリケーションをクラウド上で実現するには,どのようにすればよいのだろうか?

    重要なポイントとして, figure_titlefigure_title で起動している複数のマシンは,基本的に全く同一の OS・計算環境を有している点である. ここで,個人のコンピュータで行うようなインストールの操作を,各マシンで行うこともできるが,それは大変な手間であるし,メンテナンスも面倒だろう. すなわち,大規模な計算システムを構築するには,簡単に計算環境を複製できるような仕組みが必要であるということがわかる.

    そのような目的を実現するために使われるのが, Docker とよばれるソフトウェアである.

    Docker とは

    Docker のアイコン

    Docker とは, コンテナ (Container) とよばれる仮想環境下で,ホスト OS とは独立した別の計算環境を走らせるためのソフトウェアである. Docker を使うことで, OS を含めたすべてのプログラムをコンパクトにパッケージングすることが可能になる (パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ). Docker を使うことで,クラウドのサーバー上に瞬時に計算環境を複製することが可能になり, figure_title で見たような複数の計算機を同時に走らせるためのシステムが実現できる.

    Docker は 2013 年に Solomon Hykes らを中心に開発され,それ以降爆発的に普及し,クラウドコンピューティングだけでなく,機械学習・科学計算の文脈などでも欠かすことのできないソフトウェアとなった. Docker はエンタープライズ向けの製品を除き無料で使用することができ,コアの部分は オープンソースプロジェクト として公開されている. Docker は Linux, Windows, Mac いずれの OS でも提供されている. 概念としては, Docker は仮想マシン (Virtual machine; VM) にとても近い. ここでは, VM との対比をしながら,Docker とはなにかを簡単に説明しよう.

    仮想マシン (VM) とは,ホストとなるマシンの上に,仮想化された OS を走らせる技術である (figure_title). VM には ハイパーバイザー (Hypervisor) とよばれるレイヤーが存在する. Hypervisor はまず,物理的な計算機リソース (CPU, RAM, network など) を分割し,仮想化する. たとえば, ホストマシンに物理的な CPU が 4 コアあるとして,ハイパーバイザーはそれを (2,2) 個の組に仮想的に分割することができる. VM 上で起動する OS には,ハイパーバイザーによって仮想化されたハードウェアが割り当てられる. VM 上で起動する OS は基本的に完全に独立であり,たとえば OS-A は OS-B に割り当てられた CPU やメモリー領域にアクセスすることはできない (これを isolation とよぶ). VM を作成するための有名なソフトウェアとしては, VMwareVirtualBoxXen などがある. また,これまで触ってきた EC2 も,基本的に VM 技術を使うことで所望のスペックをもった仮想マシンがユーザーに提示される.

    Docker も, VM と同様に,仮想化された OS をホストの OS 上に走らせるための技術である. VM に対し, Docker ではハードウェアレベルの仮想化は行われておらず,すべての仮想化はソフトウェアレベルで実現されている (figure_title). Docker で走る仮想 OS は,多くの部分をホストの OS に依存しており,結果として非常にコンパクトである. その結果, Docker で仮想 OS を起動するために要する時間は, VM に比べて圧倒的に早い. また, パッケージ化された環境 (=イメージ) のサイズも完全な OS に比べ圧倒的に小さくなるので,ネットワークを通じたやり取りが非常に高速化される点も重要である 加えて, VM のいくつかの実装では,メタル (仮想化マシンに対して,物理的なハードウェア上で直接起動する場合のこと) と比べ,ハイパーバイザーレイヤーでのオーバーヘッドなどにより性能が低下することが知られているが, Docker ではメタルとほぼ同様の性能を引き出すことができるとされている.

    その他, VM との相違点などはたくさんあるのだが,ここではこれ以上詳細には立ち入らない. 大事なのは, Docker とはとてもコンパクトかつハイパフォーマンスな仮想計算環境を作るツールである,という点である. その手軽さゆえに,2013 年の登場以降,クラウドシステムでの利用が急速に増加し,現代のクラウドでは欠くことのできない中心的な技術になっている.

    Docker (左) と VM (右) の比較 (画像出典: https://www.docker.com/blog/containers-replacing-virtual-machines/)

    職業的プログラマーにとっての"三種の神器"とはなんだろうか? 多様な意見があると思うが,筆者は Git, Vim そして Docker を挙げたい.

    Git は多くの読者がご存じの通り,コードの変更を追跡するためのシステムである. Linux の作成者である Linus Torvalds によって 2005 年に誕生した. チームでの開発を進める際には欠かせないツールだ.

    Vim は 1991 年から 30 年以上の間プログラマーたちに愛されてきたテキストエディターである. Stackoverflow が行った 2019 年のアンケート によると,開発環境の部門で 5 位の人気を獲得している. たくさんのショートカットと様々なカスタム設定が提供されているので,初見の人にはなかなかハードルが高いが,一度マスターすれば他のモダンなエディターや統合開発環境に負けない,あるいはそれ以上の開発体験を実現することができる.

    これらの十年以上の歴史あるツールに並んで,第三番目の三種の神器として挙げたいのが Docker だ. Docker はプログラマーの開発のワークフローを一変させた. たとえば,プロジェクトごとに Docker イメージを作成することで,どの OS・コンピュータ でも全く同じ計算環境で開発・テストを実行することができるようになった. また, DevOpsCI / CD (Continuous Integration / Continuous Deployment) といった最近の開発ワークフローも Docker のようなコンテナ技術の存在に立脚している. さらにはサーバーレスコンピューティング ( (#sec_serverless)) といった概念も,コンテナ技術の生んだ大きな技術革新といえる.

    あなたにとっての三種の神器はなんだろうか? また,これからの未来ではどんな新しいツールが三種の神器としてプログラマーのワークフローを革新していくだろうか?

    Docker チュートリアル

    Docker とはなにかを理解するためには,実際に触って動かしてみるのが一番有効な手立てである. ここでは, Docker の簡単なチュートリアルを行っていく.

    Docker のインストールについては, (#sec:install_docker) および 公式のドキュメンテーション を参照してもらいたい. Docker のインストールが完了している前提で,以下は話を進めるものとする.

    Docker 用語集

    Docker を使い始めるに当たり,最初に主要な用語を解説しよう. 次のパラグラフで太字で強調された用語を頭に入れた上で,続くチュートリアルに取り組んでいただきたい.

    Docker を起動する際の大まかなステップを示したのが figure_title である. パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ. イメージは, Docker Hub などのリポジトリで配布されているものをダウンロードするか,自分でカスタムのイメージを作成することも可能である. イメージを作成するための”レシピ”を記述したファイルが Dockerfile である. Dockerfile からイメージを作成する操作を build とよぶ. イメージがホストマシンのメモリにロードされ,起動状態にある計算環境のことを コンテナ (Container) とよぶ. Container を起動するために使用されるコマンドが run である.

    Image と Container

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, (#sec_jupyter_and_deep_learning) でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    sh
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    dockerfile
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +    
    Skip to content

    Docker 入門

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:2.2k
    Reading:8 min

    ここまでの章で扱ってきたハンズオンでは,単一のサーバーを立ち上げ,それに SSH でログインをして,コマンドを叩くことで計算を行ってきた. いわば,パーソナルコンピュータの延長のような形でクラウドを使ってきたわけである. このような,インターネットのどこからでもアクセスできるパーソナルコンピュータとしてのクラウドという使い方も,もちろん便利であるし,いろいろな応用の可能性がある. しかし,これだけではクラウドの本当の価値は十分に発揮されていないと言うべきだろう. (#chap_cloud_basics) で述べたように,現代的なクラウドの一番の強みは自由に計算機の規模を拡大できることにある. すなわち,多数のサーバーを同時に起動し,複数のジョブを分散並列的に実行させることで大量のデータを処理してこそ,クラウドの本領が発揮されるのである.

    本章からはじまる 3 章分 (Docker 入門, (#sec_fargate_qabot), (#sec_aws_batch)) を使って,クラウドを利用することでどのように大規模な計算システムを構築しビッグデータの解析に立ち向かうのか,その片鱗をお見せしたい. とくに,前章で扱った深層学習をどのようにビッグデータに適用していくかという点に焦点を絞って議論していきたい. そのための前準備として,本章では Docker とよばれる計算機環境の仮想化ソフトウェアを紹介する (figure_title). 現代のクラウドは Docker なしには成り立たないといっても過言ではないだろう. クラウドに限らず,ローカルで行う計算処理にも Docker は大変便利である. AWS からは少し話が離れるが,しっかりと理解して前に進んでもらいたい.

    機械学習の大規模化

    先ほどから"計算システムの大規模化"と繰り返し唱えているが,それは具体的にはどのようなものを指しているのか? ここでは大規模データを処理するための計算機システムを,機械学習を例にとって見てみよう.

    (#sec_scientific_computing) で紹介した GPT-3 のような,超巨大な数のパラメータを有する深層学習モデルを学習させたいとしよう. そのような計算を行いたい場合,一つのサーバーでは計算力が到底足りない. したがって,典型的には figure_title に示すような計算システムの設計がなされる. すなわち,大量の教師データを小さなチャンクとして複数のマシンに分散し,並列的にニューラルネットのパラメータを最適化していくという構造である.

    複数の計算機を使った大規模な深層学習モデルの訓練

    あるいは,学習済みのモデルを大量のデータに適用し,解析を行いたいとしよう. たとえば, SNS のプラットフォームで大量の画像が与えられて,それぞれの写真に何が写っているのかをラベルづけする,などのアプリケーションを想定できる. そのような場合は, figure_title のようなアーキテクチャが考えられるだろう. すなわち,大量のデータを複数のマシンで分割し,それぞれのマシンで推論の計算を行うというような構造である.

    複数の計算機による深層学習モデルを使った推論計算

    このような複数の計算機を同時に走らせるようなアプリケーションをクラウド上で実現するには,どのようにすればよいのだろうか?

    重要なポイントとして, figure_titlefigure_title で起動している複数のマシンは,基本的に全く同一の OS・計算環境を有している点である. ここで,個人のコンピュータで行うようなインストールの操作を,各マシンで行うこともできるが,それは大変な手間であるし,メンテナンスも面倒だろう. すなわち,大規模な計算システムを構築するには,簡単に計算環境を複製できるような仕組みが必要であるということがわかる.

    そのような目的を実現するために使われるのが, Docker とよばれるソフトウェアである.

    Docker とは

    Docker のアイコン

    Docker とは, コンテナ (Container) とよばれる仮想環境下で,ホスト OS とは独立した別の計算環境を走らせるためのソフトウェアである. Docker を使うことで, OS を含めたすべてのプログラムをコンパクトにパッケージングすることが可能になる (パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ). Docker を使うことで,クラウドのサーバー上に瞬時に計算環境を複製することが可能になり, figure_title で見たような複数の計算機を同時に走らせるためのシステムが実現できる.

    Docker は 2013 年に Solomon Hykes らを中心に開発され,それ以降爆発的に普及し,クラウドコンピューティングだけでなく,機械学習・科学計算の文脈などでも欠かすことのできないソフトウェアとなった. Docker はエンタープライズ向けの製品を除き無料で使用することができ,コアの部分は オープンソースプロジェクト として公開されている. Docker は Linux, Windows, Mac いずれの OS でも提供されている. 概念としては, Docker は仮想マシン (Virtual machine; VM) にとても近い. ここでは, VM との対比をしながら,Docker とはなにかを簡単に説明しよう.

    仮想マシン (VM) とは,ホストとなるマシンの上に,仮想化された OS を走らせる技術である (figure_title). VM には ハイパーバイザー (Hypervisor) とよばれるレイヤーが存在する. Hypervisor はまず,物理的な計算機リソース (CPU, RAM, network など) を分割し,仮想化する. たとえば, ホストマシンに物理的な CPU が 4 コアあるとして,ハイパーバイザーはそれを (2,2) 個の組に仮想的に分割することができる. VM 上で起動する OS には,ハイパーバイザーによって仮想化されたハードウェアが割り当てられる. VM 上で起動する OS は基本的に完全に独立であり,たとえば OS-A は OS-B に割り当てられた CPU やメモリー領域にアクセスすることはできない (これを isolation とよぶ). VM を作成するための有名なソフトウェアとしては, VMwareVirtualBoxXen などがある. また,これまで触ってきた EC2 も,基本的に VM 技術を使うことで所望のスペックをもった仮想マシンがユーザーに提示される.

    Docker も, VM と同様に,仮想化された OS をホストの OS 上に走らせるための技術である. VM に対し, Docker ではハードウェアレベルの仮想化は行われておらず,すべての仮想化はソフトウェアレベルで実現されている (figure_title). Docker で走る仮想 OS は,多くの部分をホストの OS に依存しており,結果として非常にコンパクトである. その結果, Docker で仮想 OS を起動するために要する時間は, VM に比べて圧倒的に早い. また, パッケージ化された環境 (=イメージ) のサイズも完全な OS に比べ圧倒的に小さくなるので,ネットワークを通じたやり取りが非常に高速化される点も重要である 加えて, VM のいくつかの実装では,メタル (仮想化マシンに対して,物理的なハードウェア上で直接起動する場合のこと) と比べ,ハイパーバイザーレイヤーでのオーバーヘッドなどにより性能が低下することが知られているが, Docker ではメタルとほぼ同様の性能を引き出すことができるとされている.

    その他, VM との相違点などはたくさんあるのだが,ここではこれ以上詳細には立ち入らない. 大事なのは, Docker とはとてもコンパクトかつハイパフォーマンスな仮想計算環境を作るツールである,という点である. その手軽さゆえに,2013 年の登場以降,クラウドシステムでの利用が急速に増加し,現代のクラウドでは欠くことのできない中心的な技術になっている.

    Docker (左) と VM (右) の比較 (画像出典: https://www.docker.com/blog/containers-replacing-virtual-machines/)

    職業的プログラマーにとっての"三種の神器"とはなんだろうか? 多様な意見があると思うが,筆者は Git, Vim そして Docker を挙げたい.

    Git は多くの読者がご存じの通り,コードの変更を追跡するためのシステムである. Linux の作成者である Linus Torvalds によって 2005 年に誕生した. チームでの開発を進める際には欠かせないツールだ.

    Vim は 1991 年から 30 年以上の間プログラマーたちに愛されてきたテキストエディターである. Stackoverflow が行った 2019 年のアンケート によると,開発環境の部門で 5 位の人気を獲得している. たくさんのショートカットと様々なカスタム設定が提供されているので,初見の人にはなかなかハードルが高いが,一度マスターすれば他のモダンなエディターや統合開発環境に負けない,あるいはそれ以上の開発体験を実現することができる.

    これらの十年以上の歴史あるツールに並んで,第三番目の三種の神器として挙げたいのが Docker だ. Docker はプログラマーの開発のワークフローを一変させた. たとえば,プロジェクトごとに Docker イメージを作成することで,どの OS・コンピュータ でも全く同じ計算環境で開発・テストを実行することができるようになった. また, DevOpsCI / CD (Continuous Integration / Continuous Deployment) といった最近の開発ワークフローも Docker のようなコンテナ技術の存在に立脚している. さらにはサーバーレスコンピューティング ( (#sec_serverless)) といった概念も,コンテナ技術の生んだ大きな技術革新といえる.

    あなたにとっての三種の神器はなんだろうか? また,これからの未来ではどんな新しいツールが三種の神器としてプログラマーのワークフローを革新していくだろうか?

    Docker チュートリアル

    Docker とはなにかを理解するためには,実際に触って動かしてみるのが一番有効な手立てである. ここでは, Docker の簡単なチュートリアルを行っていく.

    Docker のインストールについては, (#sec:install_docker) および 公式のドキュメンテーション を参照してもらいたい. Docker のインストールが完了している前提で,以下は話を進めるものとする.

    Docker 用語集

    Docker を使い始めるに当たり,最初に主要な用語を解説しよう. 次のパラグラフで太字で強調された用語を頭に入れた上で,続くチュートリアルに取り組んでいただきたい.

    Docker を起動する際の大まかなステップを示したのが figure_title である. パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ. イメージは, Docker Hub などのリポジトリで配布されているものをダウンロードするか,自分でカスタムのイメージを作成することも可能である. イメージを作成するための”レシピ”を記述したファイルが Dockerfile である. Dockerfile からイメージを作成する操作を build とよぶ. イメージがホストマシンのメモリにロードされ,起動状態にある計算環境のことを コンテナ (Container) とよぶ. Container を起動するために使用されるコマンドが run である.

    Image と Container

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, (#sec_jupyter_and_deep_learning) でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    sh
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    dockerfile
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \
    -    && apt-get install nano
    +RUN apt-get update \
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
     
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +# copy hands-on source code in /root/
    +COPY handson/ /root/handson
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \
    -    && apt-get install nano
    +RUN apt-get update \
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
     
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    Singularity は科学計算や HPC (High Performance Computing) の分野で人気の高いコンテナプラットフォームである. Singularity では大学・研究機関の HPC クラスターでの運用に適したような設計が施されている. たとえば, Docker は基本的には root 権限で実行されるのに対し, Singularity はユーザー権限 (コマンドを実行したユーザー自身) でプログラムが実行される. root 権限での実行は Web サーバーのように個人・企業がある特定のサービスのために運用するサーバーでは問題ないが,多数のユーザーが多様な目的で計算を実行する HPC クラスターでは問題となる. また,Singularity は独自のイメージの作成方法・エコシステムをもっているが, Docker イメージを Singularity のイメージに変換し実行する機能も有している.

    podman は Red Hat 社によって開発されたもう一つのコンテナプラットフォームである. podman は基本的に Docker と同一のコマンドを採用しているが,実装は Red Hat によってスクラッチから行われた. podman では, Singularity と同様にユーザー権限でのプログラムの実行を可能であり,クラウドおよび HPC の両方の環境に対応するコンテナプラットフォームを目指して作られた. また,その名前にあるとおり pod とよばれる独自の概念が導入されている.

    著者の個人的な意見としては,現時点では Docker をマスターしておけば当面は困ることはないと考えるが,興味のある読者はぜひこれらのツールも試してみてはいかがだろうか?

    Elastic Container Service (ECS)

    ECS のアイコン

    ここまでに説明してきたように, Docker を使うことで仮想計算環境を簡単に複製・起動することが可能になる. 本章の最後の話題として, AWS 上で Docker を使った計算システムを構築する方法を解説しよう.

    Elastic Container Service (ECS) とは, Docker を使った計算機クラスターを AWS 上に作成するためのツールである (figure_title). ECS を使用することで, Docker にパッケージされたアプリケーションを計算機クラスターに投入したり,計算機クラスターのインスタンスを追加・削除する操作 (=スケーリング) を行うことができる.

    ECS の概要を示したのが figure_title である. ECS は,タスク (Task) と呼ばれる単位で管理された計算ジョブを受け付ける. システムにタスクが投入されると,ECS は最初にタスクで指定された Docker イメージを外部レジストリからダウンロードしてくる. 外部レジストリとしては, Docker Hub や AWS 独自の Docker レジストリである ECR (Elastic Container Registry) を指定することができる.

    ECS の次の重要な役割はタスクの配置である. あらかじめ定義されたクラスター内で,計算負荷が小さい仮想インスタンスを選び出し,そこに Docker イメージを配置することで指定された計算タスクが開始される. "計算負荷が小さい仮想インスタンスを選び出す" と言ったが,具体的にどのような戦略・ポリシーでこの選択を行うかは,ユーザーの指定したパラメータに従う.

    また,クラスターのスケーリングも ECS における重要な概念である. スケーリングとは,クラスター内のインスタンスの計算負荷をモニタリングし,計算負荷に応じてインスタンスの起動・停止を行う操作を指す. クラスター全体の計算負荷が指定された閾値 (たとえば 80%の稼働率) を超えていた場合,新たな仮想インスタンスをクラスター内に立ち上げる操作を scale-out (スケールアウト) とよび, 負荷が減った場合に不要なインスタンスを停止する操作を scale-in (スケールイン) とよぶ. クラスターのスケーリングは, ECS がほかの AWS のサービスと連携することで実現される. 具体的には, EC2 の Auto scaling group (ASG)Fargate の2つの選択肢が多くの場合選択される. ASG については (#sec_aws_batch), Fargate については (#sec_fargate_qabot) でより詳細に解説する.

    これら一連のタスクの管理を, ECS は自動でやってくれる. クラスターのスケーリングやタスクの配置に関してのパラメータを一度指定してしまえば,ユーザーは (ほとんどなにも考えずに) 大量のタスクを投入することができる. クラスターのスケーリングによってタスクの量にちょうど十分なだけのインスタンスが起動し,タスクが完了した後は不要なインスタンスはすべて停止される.

    さて,ここまで説明的な話が続いてしまったが,次章からは早速 Docker と AWS を使って大規模な並列計算システムを構築していこう!

    ECS の概要

    - +# copy hands-on source code in /root/ +COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    Singularity は科学計算や HPC (High Performance Computing) の分野で人気の高いコンテナプラットフォームである. Singularity では大学・研究機関の HPC クラスターでの運用に適したような設計が施されている. たとえば, Docker は基本的には root 権限で実行されるのに対し, Singularity はユーザー権限 (コマンドを実行したユーザー自身) でプログラムが実行される. root 権限での実行は Web サーバーのように個人・企業がある特定のサービスのために運用するサーバーでは問題ないが,多数のユーザーが多様な目的で計算を実行する HPC クラスターでは問題となる. また,Singularity は独自のイメージの作成方法・エコシステムをもっているが, Docker イメージを Singularity のイメージに変換し実行する機能も有している.

    podman は Red Hat 社によって開発されたもう一つのコンテナプラットフォームである. podman は基本的に Docker と同一のコマンドを採用しているが,実装は Red Hat によってスクラッチから行われた. podman では, Singularity と同様にユーザー権限でのプログラムの実行を可能であり,クラウドおよび HPC の両方の環境に対応するコンテナプラットフォームを目指して作られた. また,その名前にあるとおり pod とよばれる独自の概念が導入されている.

    著者の個人的な意見としては,現時点では Docker をマスターしておけば当面は困ることはないと考えるが,興味のある読者はぜひこれらのツールも試してみてはいかがだろうか?

    Elastic Container Service (ECS)

    ECS のアイコン

    ここまでに説明してきたように, Docker を使うことで仮想計算環境を簡単に複製・起動することが可能になる. 本章の最後の話題として, AWS 上で Docker を使った計算システムを構築する方法を解説しよう.

    Elastic Container Service (ECS) とは, Docker を使った計算機クラスターを AWS 上に作成するためのツールである (figure_title). ECS を使用することで, Docker にパッケージされたアプリケーションを計算機クラスターに投入したり,計算機クラスターのインスタンスを追加・削除する操作 (=スケーリング) を行うことができる.

    ECS の概要を示したのが figure_title である. ECS は,タスク (Task) と呼ばれる単位で管理された計算ジョブを受け付ける. システムにタスクが投入されると,ECS は最初にタスクで指定された Docker イメージを外部レジストリからダウンロードしてくる. 外部レジストリとしては, Docker Hub や AWS 独自の Docker レジストリである ECR (Elastic Container Registry) を指定することができる.

    ECS の次の重要な役割はタスクの配置である. あらかじめ定義されたクラスター内で,計算負荷が小さい仮想インスタンスを選び出し,そこに Docker イメージを配置することで指定された計算タスクが開始される. "計算負荷が小さい仮想インスタンスを選び出す" と言ったが,具体的にどのような戦略・ポリシーでこの選択を行うかは,ユーザーの指定したパラメータに従う.

    また,クラスターのスケーリングも ECS における重要な概念である. スケーリングとは,クラスター内のインスタンスの計算負荷をモニタリングし,計算負荷に応じてインスタンスの起動・停止を行う操作を指す. クラスター全体の計算負荷が指定された閾値 (たとえば 80%の稼働率) を超えていた場合,新たな仮想インスタンスをクラスター内に立ち上げる操作を scale-out (スケールアウト) とよび, 負荷が減った場合に不要なインスタンスを停止する操作を scale-in (スケールイン) とよぶ. クラスターのスケーリングは, ECS がほかの AWS のサービスと連携することで実現される. 具体的には, EC2 の Auto scaling group (ASG)Fargate の2つの選択肢が多くの場合選択される. ASG については (#sec_aws_batch), Fargate については (#sec_fargate_qabot) でより詳細に解説する.

    これら一連のタスクの管理を, ECS は自動でやってくれる. クラスターのスケーリングやタスクの配置に関してのパラメータを一度指定してしまえば,ユーザーは (ほとんどなにも考えずに) 大量のタスクを投入することができる. クラスターのスケーリングによってタスクの量にちょうど十分なだけのインスタンスが起動し,タスクが完了した後は不要なインスタンスはすべて停止される.

    さて,ここまで説明的な話が続いてしまったが,次章からは早速 Docker と AWS を使って大規模な並列計算システムを構築していこう!

    ECS の概要

    + \ No newline at end of file diff --git a/development/aws/handson-bashoutter.html b/development/aws/handson-bashoutter.html index 2e3cf1b0..21daa332 100644 --- a/development/aws/handson-bashoutter.html +++ b/development/aws/handson-bashoutter.html @@ -5,16 +5,16 @@ Hands-on #6: Bashoutter | Toshiki's Note - + - + - + - + @@ -37,416 +37,416 @@ -
    Skip to content

    Hands-on #6: Bashoutter

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:2.9k
    Reading:12 min

    さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

    ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

    準備

    ハンズオンのソースコードは GitHub の handson/bashoutter に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. それ以外に必要な準備はない.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行できる.

    アプリケーションの説明

    API

    今回のアプリケーションでは,人々からの俳句の投稿を受け付けたり,投稿された俳句の一覧を取得する,といった機能を実装したい. この機能を実現するための最小限の設計として, table_title に示すような四つの REST API を今回は実装する. 俳句を投稿する,閲覧する,削除するという基本的なデータ操作を行うための API が完備されている. また, PATCH /haiku/{item_id} は, {item_id} で指定された俳句に”いいね”をするために使用する.

    Bashoutter API

    GET /haiku

    俳句の一覧を取得する

    POST /haiku

    新しい俳句を投稿する

    PATCH /haiku/{item_id}

    {item_id} で指定された俳句にお気に入り票を一つ入れる

    DELETE /haiku/{item_id}

    {item_id} で指定された俳句を削除する

    それぞれの API のパラメータおよび返り値の詳細は,ハンズオンのソースコードの中の swagger.yml に定義してある.

    Open API Specification (OAS; 少し前は Swagger Specification とよばれていた) は, REST API のための記述フォーマットである. OAS に従って API の仕様が記述されていると,簡単にドキュメンテーションを生成したり,クライアントアプリケーションを自動生成することができる. 今回用意した API 仕様 も, OAS に従って書いてある. 詳しくは Swagger の公式ドキュメンテーション などを参照.

    アプリケーションアーキテクチャ

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#5で作製するアプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントからの API リクエストは, API Gateway (後述)にまず送信され, API の URI で指定された Lambda 関数へ転送される.

    • それぞれの API のパス (リソース) ごとに独立した Lambda を用意する.

    • 俳句の情報 (作者,本文,投稿日時など) を記録するためのデータベース (DynamoDB) を用意する.

    • 各 Lambda 関数には, DynamoDB へのアクセス権を付与する.

    • 最後に,ウェブブラウザからコンテンツを表示できるよう, ウェブページの静的コンテンツを配信するための S3 バケットを用意する.クライアントはこの S3 バケットにアクセスすることで HTML/CSS/JS などのコンテンツを取得する.

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    python
    class Bashoutter(core.Stack):
    +    
    Skip to content

    Hands-on #6: Bashoutter

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:2.9k
    Reading:12 min

    さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

    ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

    準備

    ハンズオンのソースコードは GitHub の handson/bashoutter に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. それ以外に必要な準備はない.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行できる.

    アプリケーションの説明

    API

    今回のアプリケーションでは,人々からの俳句の投稿を受け付けたり,投稿された俳句の一覧を取得する,といった機能を実装したい. この機能を実現するための最小限の設計として, table_title に示すような四つの REST API を今回は実装する. 俳句を投稿する,閲覧する,削除するという基本的なデータ操作を行うための API が完備されている. また, PATCH /haiku/{item_id} は, {item_id} で指定された俳句に”いいね”をするために使用する.

    Bashoutter API

    GET /haiku

    俳句の一覧を取得する

    POST /haiku

    新しい俳句を投稿する

    PATCH /haiku/{item_id}

    {item_id} で指定された俳句にお気に入り票を一つ入れる

    DELETE /haiku/{item_id}

    {item_id} で指定された俳句を削除する

    それぞれの API のパラメータおよび返り値の詳細は,ハンズオンのソースコードの中の swagger.yml に定義してある.

    Open API Specification (OAS; 少し前は Swagger Specification とよばれていた) は, REST API のための記述フォーマットである. OAS に従って API の仕様が記述されていると,簡単にドキュメンテーションを生成したり,クライアントアプリケーションを自動生成することができる. 今回用意した API 仕様 も, OAS に従って書いてある. 詳しくは Swagger の公式ドキュメンテーション などを参照.

    アプリケーションアーキテクチャ

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#5で作製するアプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントからの API リクエストは, API Gateway (後述)にまず送信され, API の URI で指定された Lambda 関数へ転送される.

    • それぞれの API のパス (リソース) ごとに独立した Lambda を用意する.

    • 俳句の情報 (作者,本文,投稿日時など) を記録するためのデータベース (DynamoDB) を用意する.

    • 各 Lambda 関数には, DynamoDB へのアクセス権を付与する.

    • 最後に,ウェブブラウザからコンテンツを表示できるよう, ウェブページの静的コンテンツを配信するための S3 バケットを用意する.クライアントはこの S3 バケットにアクセスすることで HTML/CSS/JS などのコンテンツを取得する.

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    python
    class Bashoutter(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
     
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
     
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
     
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
     
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
     
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    class Bashoutter(core.Stack):
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    class Bashoutter(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
     
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
     
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
     
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
     
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
     
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

    • 静的コンテンツを配信するための S3 バケットを用意している.

    • それぞれの API で実行される Lambda 関数を定義している. 関数は Python3.7 で書かれており,コードは handson/bashoutter/api/api.py にある.

    • <3> で定義された Lambda 関数に対し,データベースへの読み書きのアクセス権限を付与している.

    • ここで,API Gateway により,各 API パスとそこで実行されるべき Lambda 関数を紐付けている.

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    python
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    今回のハンズオンでは説明の簡略化のため CloudFront の設定を行わなかったが,興味のある読者は次のリンクのプログラムが参考になるだろう.

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    python
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    python
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

    • 静的コンテンツを配信するための S3 バケットを用意している.

    • それぞれの API で実行される Lambda 関数を定義している. 関数は Python3.7 で書かれており,コードは handson/bashoutter/api/api.py にある.

    • <3> で定義された Lambda 関数に対し,データベースへの読み書きのアクセス権限を付与している.

    • ここで,API Gateway により,各 API パスとそこで実行されるべき Lambda 関数を紐付けている.

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    python
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    今回のハンズオンでは説明の簡略化のため CloudFront の設定を行わなかったが,興味のある読者は次のリンクのプログラムが参考になるだろう.

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    python
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    python
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
     
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
     
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
     
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
     
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    python
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は (#sec_aws_batch) で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    そのような理由により,このコードでは GET のハンドラー関数に対しては grant_read_data() によって, read 権限のみを付与している.

    API Gateway

    API Gateway とは, API の"入り口"として,API のリクエストパスに従って Lambda や EC2 などに接続を行うという機能を担う (figure_title). Lambda や EC2 によって行われた処理の結果は,再び API Gateway を経由してクライアントに返される. このように,クライアントとバックエンドサーバーの間に立ち, API のリソースパスに応じて接続先を振り分けるようなサーバーをルーター,あるいはリバースプロキシとよんだりする. 従来的には,ルーターにはそれ専用の仮想サーバーが置かれることが一般的であった. しかし, API Gateway はサーバーレスなルーターとして,固定されたサーバーを配置することなく, API のリクエストが来たときのみ起動し,API のルーティングを実行する. サーバーレスであることの当然の帰結として,アクセスの件数が増大したときにはそれにルーティングの処理能力を自動で増やす機能も備わっている.

    API Gateway

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    python
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    python
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は (#sec_aws_batch) で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    そのような理由により,このコードでは GET のハンドラー関数に対しては grant_read_data() によって, read 権限のみを付与している.

    API Gateway

    API Gateway とは, API の"入り口"として,API のリクエストパスに従って Lambda や EC2 などに接続を行うという機能を担う (figure_title). Lambda や EC2 によって行われた処理の結果は,再び API Gateway を経由してクライアントに返される. このように,クライアントとバックエンドサーバーの間に立ち, API のリソースパスに応じて接続先を振り分けるようなサーバーをルーター,あるいはリバースプロキシとよんだりする. 従来的には,ルーターにはそれ専用の仮想サーバーが置かれることが一般的であった. しかし, API Gateway はサーバーレスなルーターとして,固定されたサーバーを配置することなく, API のリクエストが来たときのみ起動し,API のルーティングを実行する. サーバーレスであることの当然の帰結として,アクセスの件数が増大したときにはそれにルーティングの処理能力を自動で増やす機能も備わっている.

    API Gateway

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    python
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
     
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
     
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
     
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
     
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

    • 次に, api.root.add_resource() のメソッドを呼ぶことで, /haiku という API パスを追加している.

    • 続いて, add_method() を呼ぶことで, GET, POST のメソッドを /haiku のパスに定義している.

    • さらに, haiku.add_resource("{item_id}") により, /haiku/{item_id} という API パスを追加している.

    • 最後に, add_method() を呼ぶことにより, PATCH, DELETE のメソッドを /haiku/{item_id} のパスに定義している.

    このように, API Gateway の使い方は非常にシンプルで,逐次的に API パスとそこで実行されるメソッド・Lambda を記述していくだけでよい.

    このプログラムで 新規 API を作成すると, ランダムな URL がその API のエンドポイントとして割り当てられる. これを. api.example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

    • 次に, api.root.add_resource() のメソッドを呼ぶことで, /haiku という API パスを追加している.

    • 続いて, add_method() を呼ぶことで, GET, POST のメソッドを /haiku のパスに定義している.

    • さらに, haiku.add_resource("{item_id}") により, /haiku/{item_id} という API パスを追加している.

    • 最後に, add_method() を呼ぶことにより, PATCH, DELETE のメソッドを /haiku/{item_id} のパスに定義している.

    このように, API Gateway の使い方は非常にシンプルで,逐次的に API パスとそこで実行されるメソッド・Lambda を記述していくだけでよい.

    このプログラムで 新規 API を作成すると, ランダムな URL がその API のエンドポイントとして割り当てられる. これを. api.example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    API Gateway コンソール画面 (1)

    今回デプロイした "BashoutterApi" という名前の API をクリックすることで figure_title のような画面に遷移し,詳細情報を閲覧できる. GET /haiku, POST /haiku などが定義されていることが確認できる.

    それぞれのメソッドをクリックすると,そのメソッドの詳細情報を確認できる. API Gateway は,前述したルーティングの機能だけでなく,認証機能などを追加することも可能である. このハンズオンではとくにこれらの機能は使用しないが, "Method Request" と書いてある項目などがそれに相当する. 次に, figure_title で画面右端の赤色で囲った部分に,この API で呼ばれる Lambda 関数が指定されていることに注目しよう. 関数名をクリックと,該当する Lambda のコンソールに遷移し,関数の中身を閲覧することが可能である.

    API Gateway コンソール画面 (2)

    次に, S3 のコンソール画面に移ってみよう. bashouter- で始まるランダムな名前のバケットが見つかるはずである (figure_title).

    S3 コンソール画面

    バケットの名前をクリックすることで,バケットの中身を確認してみよう. index.html のほか, css/, js/ などのディレクトリがあるのが確認できるだろう (figure_title). これらが,ウェブページの"枠"を定義している静的コンテンツである.

    S3 バケットの中身

    API リクエストを送信する

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"

    次のような出力が得られるだろう.

    sh
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    API Gateway コンソール画面 (1)

    今回デプロイした "BashoutterApi" という名前の API をクリックすることで figure_title のような画面に遷移し,詳細情報を閲覧できる. GET /haiku, POST /haiku などが定義されていることが確認できる.

    それぞれのメソッドをクリックすると,そのメソッドの詳細情報を確認できる. API Gateway は,前述したルーティングの機能だけでなく,認証機能などを追加することも可能である. このハンズオンではとくにこれらの機能は使用しないが, "Method Request" と書いてある項目などがそれに相当する. 次に, figure_title で画面右端の赤色で囲った部分に,この API で呼ばれる Lambda 関数が指定されていることに注目しよう. 関数名をクリックと,該当する Lambda のコンソールに遷移し,関数の中身を閲覧することが可能である.

    API Gateway コンソール画面 (2)

    次に, S3 のコンソール画面に移ってみよう. bashouter- で始まるランダムな名前のバケットが見つかるはずである (figure_title).

    S3 コンソール画面

    バケットの名前をクリックすることで,バケットの中身を確認してみよう. index.html のほか, css/, js/ などのディレクトリがあるのが確認できるだろう (figure_title). これらが,ウェブページの"枠"を定義している静的コンテンツである.

    S3 バケットの中身

    API リクエストを送信する

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"

    次のような出力が得られるだろう.

    sh
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
     
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
     
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている ( (#fig:web_server) 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    ウェブブラウザを開き,アドレスバーに S3 の URL を入力しへアクセスしてみよう. すると, figure_title のようなページが表示されるはずである.

    "Bashoutter" の GUI 画面

    ページが表示されたら,一番上の "API Endpoint URL" と書いてあるテキストボックスに,今回デプロイした API Gateway の URL を入力する (今回のアプリケーションでは,API Gateway の URL はランダムに割り当てられるのでこのような GUI の仕様になっている). そうしたら,画面の "REFRESH" と書いてあるボタンを押してみよう. データベースに俳句が登録済みであれば,俳句の一覧が表示されるはずである. 各俳句の左下にあるハートのアイコンをクリックすることで, "like" の票を入れることができる.

    新しい俳句を投稿するには,五七五と投稿者の名前を入力して, "POST" を押す. "POST" を押した後は,再び "REFRESH" ボタンを押すことで最新の俳句のリストをデータベースから取得する.

    アプリケーションの削除

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. (#sec_intro_serverless) では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    これらの演習を通じて,世の中のウェブサービスがどのようにしてでき上がっているのか,少し理解が深まっただろうか? また,そのようなウェブアプリケーションを自分が作りたいと思ったとき,今回のハンズオンがその出発点となることができたならば幸いである.

    - +HTTP/1.1 200 OK +Connection: keep-alive +Content-Length: 258 +Content-Type: application/json +... +[ + { + "created_at": "2020-07-06T02:46:04+00:00", + "first": "閑さや", + "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b", + "likes": 0.0, + "second": "岩にしみ入る", + "third": "蝉の声", + "username": "松尾芭蕉" + } +]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている ( (#fig:web_server) 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    ウェブブラウザを開き,アドレスバーに S3 の URL を入力しへアクセスしてみよう. すると, figure_title のようなページが表示されるはずである.

    "Bashoutter" の GUI 画面

    ページが表示されたら,一番上の "API Endpoint URL" と書いてあるテキストボックスに,今回デプロイした API Gateway の URL を入力する (今回のアプリケーションでは,API Gateway の URL はランダムに割り当てられるのでこのような GUI の仕様になっている). そうしたら,画面の "REFRESH" と書いてあるボタンを押してみよう. データベースに俳句が登録済みであれば,俳句の一覧が表示されるはずである. 各俳句の左下にあるハートのアイコンをクリックすることで, "like" の票を入れることができる.

    新しい俳句を投稿するには,五七五と投稿者の名前を入力して, "POST" を押す. "POST" を押した後は,再び "REFRESH" ボタンを押すことで最新の俳句のリストをデータベースから取得する.

    アプリケーションの削除

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. (#sec_intro_serverless) では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    これらの演習を通じて,世の中のウェブサービスがどのようにしてでき上がっているのか,少し理解が深まっただろうか? また,そのようなウェブアプリケーションを自分が作りたいと思ったとき,今回のハンズオンがその出発点となることができたならば幸いである.

    + \ No newline at end of file diff --git a/development/aws/handson-ec2.html b/development/aws/handson-ec2.html index 5d65966f..a2d35939 100644 --- a/development/aws/handson-ec2.html +++ b/development/aws/handson-ec2.html @@ -5,17 +5,17 @@ Hands-on #1: 初めての EC2 インスタンスを起動する | Toshiki's Note - + - + - + - + @@ -38,200 +38,200 @@ -
    Skip to content

    Hands-on #1: 初めての EC2 インスタンスを起動する

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:2.6k
    Reading:11 min

    ハンズオンの第一回では, CDK を使って EC2 のインスタンス(仮想サーバー)を作成し,SSH でサーバーにログインする,という演習を行う. このハンズオンを終えれば,あなたは自分だけのサーバーを AWS 上に立ち上げ,自由に計算を走らせることができるようになるのである!

    準備

    ハンズオンのソースコードは GitHub の handson/ec2-get-started に置いてある.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行することができる.

    まずは,ハンズオンを実行するための環境を整える. これらの環境整備は,後のハンズオンでも前提となるものなので確実にミスなく行っていただきたい.

    • AWS Account: ハンズオンを実行するには個人の AWS アカウントが必要である. AWS アカウントの取得については (#sec:create_aws_account) を参照のこと.

    • Python と Node.js: 本ハンズオンを実行するには,Python (3.6 以上),Node.js (12.0 以上) がインストールされていなければならない.

    • AWS CLI: AWS CLI のインストールについては, (#aws_cli_install) を参照. ここに記載されている認証鍵の設定も済ませておくこと.

    • AWS CDK: AWS CDK のインストールについては, (#aws_cdk_install) を参照.

    • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.

    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    使用方法については (#sec_handson_docker) を参照のこと.

    SSH

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する ( (#environments) を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    python
    class MyFirstEc2(core.Stack):
    +    
    Skip to content

    Hands-on #1: 初めての EC2 インスタンスを起動する

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:2.6k
    Reading:11 min

    ハンズオンの第一回では, CDK を使って EC2 のインスタンス(仮想サーバー)を作成し,SSH でサーバーにログインする,という演習を行う. このハンズオンを終えれば,あなたは自分だけのサーバーを AWS 上に立ち上げ,自由に計算を走らせることができるようになるのである!

    準備

    ハンズオンのソースコードは GitHub の handson/ec2-get-started に置いてある.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行することができる.

    まずは,ハンズオンを実行するための環境を整える. これらの環境整備は,後のハンズオンでも前提となるものなので確実にミスなく行っていただきたい.

    • AWS Account: ハンズオンを実行するには個人の AWS アカウントが必要である. AWS アカウントの取得については (#sec:create_aws_account) を参照のこと.

    • Python と Node.js: 本ハンズオンを実行するには,Python (3.6 以上),Node.js (12.0 以上) がインストールされていなければならない.

    • AWS CLI: AWS CLI のインストールについては, (#aws_cli_install) を参照. ここに記載されている認証鍵の設定も済ませておくこと.

    • AWS CDK: AWS CDK のインストールについては, (#aws_cdk_install) を参照.

    • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.

    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    使用方法については (#sec_handson_docker) を参照のこと.

    SSH

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する ( (#environments) を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    python
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class MyFirstEc2(core.Stack):
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    • まず最初に,VPC を定義する.

    • 次に, security group (SG) を定義している. ここでは,任意の IPv4 のアドレスからの,ポート 22 (SSH の接続に使用される)への接続を許可している. それ以外の接続は拒絶される.

    • 最後に,上記で作った VPC と SG が付与された EC2 インスタンスを作成している. インスタンスタイプは t2.micro を選択し, Amazon Linux を OS として設定している.

    それぞれについて,もう少し詳しく説明しよう.

    VPC (Virtual Private Cloud)

    VPC のアイコン.

    VPC

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    python
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

    • cidr="10.10.0.0/23" : このパラメータは,VPC 内の IPv4 のレンジを指定している. CIDR 記法については, Wikipediaなどを参照. 10.10.0.0/2310.10.0.0 から 10.10.1.255 までの 512 個の連続したアドレス範囲を指している. つまり,この VPC では最大で 512 個のユニークな IPv4 アドレスが使えることになる. 今回はサーバーは一つなので 512 個は明らかに多すぎるが,VPC はアドレスの数はどれだけ作成しても無料なので,多めに作成した.

    • subnet_configuration=... : このパラメータは,VPC にどのようなサブネットを作るか,を決めている. サブネットの種類には private subnetpublic subnet の二種類がある. private subnet は基本的にインターネットとは遮断されたサブネット環境である. インターネットと繋がっていないので,セキュリティは極めて高く, VPC 内のサーバーとのみ通信を行えばよい EC2 インスタンスはここに配置する. Public subnet とはインターネットに繋がったサブネットである. 本ハンズオンで作成するサーバーは,外から SSH でログインを行いたいので, Public subnet 内に配置する. より詳細な記述は 公式ドキュメンテーション を参照.

    • natgateways=0 : これは少し高度な内容なので省略する (興味のある読者は 公式ドキュメンテーションを参照). が,これを 0 にしておかないと,NAT Gateway の利用料金が発生してしまうので,注意!

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    python
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    EC2 (Elastic Compute Cloud)

    EC2 のアイコン.

    EC2

    EC2 は AWS 上に仮想サーバーを立ち上げるサービスである. 個々の起動状態にある仮想サーバーのことをインスタンス (instance) とよぶ (しかし,口語的なコミュニケーションにおいては,サーバーとインスタンスという言葉は相互互換的に用いられることが多い).

    EC2 では用途に応じて様々なインスタンスタイプが提供されている. table_title に,代表的なインスタンスタイプの例を挙げる (執筆時点での情報). EC2 のインスタンスタイプのすべてのリストは 公式ドキュメンテーション "Amazon EC2 Instance Types" で見ることができる.

    EC2 instance types

    InstancevCPUMemory (GiB)Network bandwidth (Gbps)Price per hour ($)
    t2.micro11-0.0116
    t2.small12-0.023
    t2.medium24-0.0464
    c5.24xlarge96192254.08
    c5n.18xlarge721921003.888
    x1e.16xlarge6419521013.344

    table_title からわかるように, CPU は 1 コアから 96 コアまで,メモリーは 1GB から 2TB 以上まで,ネットワーク帯域は最大で 100Gbps まで,幅広く選択することができる. また,時間あたりの料金は,CPU・メモリーの占有数にほぼ比例する形で増加する. EC2 はサーバーの起動時間を秒単位で記録しており,利用料金は使用時間に比例する形で決定される. 例えば, t2.medium のインスタンスを 10 時間起動した場合,0.0464 * 10 = 0.464 ドルの料金が発生する.

    AWS には 無料利用枠 というものがあり, t2.micro であれば月に 750 時間までは無料で利用することができる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    python
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, (#sec_jupyter_and_deep_learning) でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    さて,ハンズオンのコードの理解ができたところで,プログラムを実際に実行してみよう.繰り返しになるが, 準備 での準備ができていることが前提である.

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    sh
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は (#venv_quick_guide) に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    AWS のシークレットキーをセットする

    AWS CLI および AWS CDK を使うには, AWS のシークレットキーが設定されている必要がある. シークレットキーの発行については (#aws_secrets) を参照のこと. シークレットキーを発行したら, (#aws_cli_install) を参照し,コマンドラインの設定を行う.

    手順をここに短く要約すると,一つ目の方法は AWS_ACCESS_KEY_ID などの環境変数を設定するやり方である. もう一つの方法は, ~/.aws/credentials に認証情報を保存しておく方式である. シークレットキーの設定は AWS CLI/CDK を使用するうえで共通のステップになるので,しっかりと理解しておくように.

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    sh
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    sh
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    おめでとう!これで,めでたく AWS 上に EC2 仮想サーバーを起動し,リモートからアクセスできるようになった!

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    sh
    $ cat /proc/cpuinfo
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    • まず最初に,VPC を定義する.

    • 次に, security group (SG) を定義している. ここでは,任意の IPv4 のアドレスからの,ポート 22 (SSH の接続に使用される)への接続を許可している. それ以外の接続は拒絶される.

    • 最後に,上記で作った VPC と SG が付与された EC2 インスタンスを作成している. インスタンスタイプは t2.micro を選択し, Amazon Linux を OS として設定している.

    それぞれについて,もう少し詳しく説明しよう.

    VPC (Virtual Private Cloud)

    VPC のアイコン.

    VPC

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    python
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

    • cidr="10.10.0.0/23" : このパラメータは,VPC 内の IPv4 のレンジを指定している. CIDR 記法については, Wikipediaなどを参照. 10.10.0.0/2310.10.0.0 から 10.10.1.255 までの 512 個の連続したアドレス範囲を指している. つまり,この VPC では最大で 512 個のユニークな IPv4 アドレスが使えることになる. 今回はサーバーは一つなので 512 個は明らかに多すぎるが,VPC はアドレスの数はどれだけ作成しても無料なので,多めに作成した.

    • subnet_configuration=... : このパラメータは,VPC にどのようなサブネットを作るか,を決めている. サブネットの種類には private subnetpublic subnet の二種類がある. private subnet は基本的にインターネットとは遮断されたサブネット環境である. インターネットと繋がっていないので,セキュリティは極めて高く, VPC 内のサーバーとのみ通信を行えばよい EC2 インスタンスはここに配置する. Public subnet とはインターネットに繋がったサブネットである. 本ハンズオンで作成するサーバーは,外から SSH でログインを行いたいので, Public subnet 内に配置する. より詳細な記述は 公式ドキュメンテーション を参照.

    • natgateways=0 : これは少し高度な内容なので省略する (興味のある読者は 公式ドキュメンテーションを参照). が,これを 0 にしておかないと,NAT Gateway の利用料金が発生してしまうので,注意!

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    python
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    EC2 (Elastic Compute Cloud)

    EC2 のアイコン.

    EC2

    EC2 は AWS 上に仮想サーバーを立ち上げるサービスである. 個々の起動状態にある仮想サーバーのことをインスタンス (instance) とよぶ (しかし,口語的なコミュニケーションにおいては,サーバーとインスタンスという言葉は相互互換的に用いられることが多い).

    EC2 では用途に応じて様々なインスタンスタイプが提供されている. table_title に,代表的なインスタンスタイプの例を挙げる (執筆時点での情報). EC2 のインスタンスタイプのすべてのリストは 公式ドキュメンテーション "Amazon EC2 Instance Types" で見ることができる.

    EC2 instance types

    InstancevCPUMemory (GiB)Network bandwidth (Gbps)Price per hour ($)
    t2.micro11-0.0116
    t2.small12-0.023
    t2.medium24-0.0464
    c5.24xlarge96192254.08
    c5n.18xlarge721921003.888
    x1e.16xlarge6419521013.344

    table_title からわかるように, CPU は 1 コアから 96 コアまで,メモリーは 1GB から 2TB 以上まで,ネットワーク帯域は最大で 100Gbps まで,幅広く選択することができる. また,時間あたりの料金は,CPU・メモリーの占有数にほぼ比例する形で増加する. EC2 はサーバーの起動時間を秒単位で記録しており,利用料金は使用時間に比例する形で決定される. 例えば, t2.medium のインスタンスを 10 時間起動した場合,0.0464 * 10 = 0.464 ドルの料金が発生する.

    AWS には 無料利用枠 というものがあり, t2.micro であれば月に 750 時間までは無料で利用することができる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    python
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, (#sec_jupyter_and_deep_learning) でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    さて,ハンズオンのコードの理解ができたところで,プログラムを実際に実行してみよう.繰り返しになるが, 準備 での準備ができていることが前提である.

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    sh
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は (#venv_quick_guide) に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    AWS のシークレットキーをセットする

    AWS CLI および AWS CDK を使うには, AWS のシークレットキーが設定されている必要がある. シークレットキーの発行については (#aws_secrets) を参照のこと. シークレットキーを発行したら, (#aws_cli_install) を参照し,コマンドラインの設定を行う.

    手順をここに短く要約すると,一つ目の方法は AWS_ACCESS_KEY_ID などの環境変数を設定するやり方である. もう一つの方法は, ~/.aws/credentials に認証情報を保存しておく方式である. シークレットキーの設定は AWS CLI/CDK を使用するうえで共通のステップになるので,しっかりと理解しておくように.

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    sh
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    sh
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    おめでとう!これで,めでたく AWS 上に EC2 仮想サーバーを起動し,リモートからアクセスできるようになった!

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    sh
    $ cat /proc/cpuinfo
     
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    $ cat /proc/cpuinfo
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB
    $ cat /proc/cpuinfo
     
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    bash
    $  top -n 1
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    bash
    $  top -n 1
     
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
     
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
     
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
     
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    sh
    $ sudo yum update -y
    -$ sudo yum install -y python36
    $ sudo yum update -y
    -$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    sh
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    EC2 コンソール画面

    コンソール右上で,正しいリージョン (今回の場合は ap-northeast-1, Tokyo) が選択されているか,注意する!

    前章で CloudFormation について触れたが,今回デプロイしたアプリケーションも,CloudFormation のスタックとして管理されている. スタック (stack) とは, AWS リソースの集合のことを指す. 今回の場合は, VPC/EC2/SG などがスタックの中に含まれている. コンソールで CloudFormation のページに行ってみよう (figure_title).

    CloudFormation コンソール画面

    "MyFirstEc2" という名前のスタックがあることが確認できる. クリックをして中身を見てみると,EC2, VPC などのリソースがこのスタックに紐付いていることがわかる.

    スタックを削除

    これにて,第一回のハンズオンで説明すべき事柄はすべて完了した. 最後に,使わなくなったスタックを削除しよう. スタックの削除には,二つの方法がある.

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    ここまでが,本書の第一部の内容である. 盛りだくさんの内容であったが,ついてこれたであろうか?

    (#chap_cloud_basics) では,クラウドの定義と用語の説明を行ったあと,なぜクラウドを使うのか,という点を議論した. 続いて (#sec_aws_general_introduction) では,クラウドを学ぶ具体的なプラットフォームとして AWS を取り上げ, AWS を使用するにあたり最低限必要な知識と用語の説明を行った. さらに, Hands-on #1: 初めての EC2 インスタンスを起動する のハンズオンでは AWS CLI と AWS CDK を使って,自身のプライベートなサーバーを AWS 上に立ち上げる演習を行った.

    これらを通じて,いかに簡単に (たった数行のコマンドで!) 仮想サーバーを立ち上げたり,削除したりすることができるか,体験できただろう. 筆者は, (#chap_cloud_basics) でクラウドの最も重要な側面はダイナミックに計算リソースを拡大・縮小できることである,と述べた. この言葉の意味が,ハンズオンを通じてより明らかになっただろうか? ここで学んだ技術を少し応用するだけで,自分のウェブページをホストする仮想サーバーを作成したり,大量のコアを搭載した EC2 インスタンスを用意して科学計算を実行するなど,いろいろなアプリケーションが実現できる.

    次章からは,今回学んだクラウドの技術を基に,より現実に即した問題を解くことを体験してもらう. お楽しみに!

    - + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 1 root 20 0 19696 2596 2268 S 0.0 0.3 0:01.21 init + 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd + 3 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    sh
    $ sudo yum update -y
    +$ sudo yum install -y python36
    $ sudo yum update -y
    +$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    sh
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    EC2 コンソール画面

    コンソール右上で,正しいリージョン (今回の場合は ap-northeast-1, Tokyo) が選択されているか,注意する!

    前章で CloudFormation について触れたが,今回デプロイしたアプリケーションも,CloudFormation のスタックとして管理されている. スタック (stack) とは, AWS リソースの集合のことを指す. 今回の場合は, VPC/EC2/SG などがスタックの中に含まれている. コンソールで CloudFormation のページに行ってみよう (figure_title).

    CloudFormation コンソール画面

    "MyFirstEc2" という名前のスタックがあることが確認できる. クリックをして中身を見てみると,EC2, VPC などのリソースがこのスタックに紐付いていることがわかる.

    スタックを削除

    これにて,第一回のハンズオンで説明すべき事柄はすべて完了した. 最後に,使わなくなったスタックを削除しよう. スタックの削除には,二つの方法がある.

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    ここまでが,本書の第一部の内容である. 盛りだくさんの内容であったが,ついてこれたであろうか?

    (#chap_cloud_basics) では,クラウドの定義と用語の説明を行ったあと,なぜクラウドを使うのか,という点を議論した. 続いて (#sec_aws_general_introduction) では,クラウドを学ぶ具体的なプラットフォームとして AWS を取り上げ, AWS を使用するにあたり最低限必要な知識と用語の説明を行った. さらに, Hands-on #1: 初めての EC2 インスタンスを起動する のハンズオンでは AWS CLI と AWS CDK を使って,自身のプライベートなサーバーを AWS 上に立ち上げる演習を行った.

    これらを通じて,いかに簡単に (たった数行のコマンドで!) 仮想サーバーを立ち上げたり,削除したりすることができるか,体験できただろう. 筆者は, (#chap_cloud_basics) でクラウドの最も重要な側面はダイナミックに計算リソースを拡大・縮小できることである,と述べた. この言葉の意味が,ハンズオンを通じてより明らかになっただろうか? ここで学んだ技術を少し応用するだけで,自分のウェブページをホストする仮想サーバーを作成したり,大量のコアを搭載した EC2 インスタンスを用意して科学計算を実行するなど,いろいろなアプリケーションが実現できる.

    次章からは,今回学んだクラウドの技術を基に,より現実に即した問題を解くことを体験してもらう. お楽しみに!

    + \ No newline at end of file diff --git a/development/aws/handson-jupyter.html b/development/aws/handson-jupyter.html index fde60e6a..7623808e 100644 --- a/development/aws/handson-jupyter.html +++ b/development/aws/handson-jupyter.html @@ -5,16 +5,16 @@ Hands-on #2: AWS でディープラーニングを実践 | Toshiki's Note - + - + - + - + @@ -37,254 +37,254 @@ -
    Skip to content

    Hands-on #2: AWS でディープラーニングを実践

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:3.2k
    Reading:14 min

    準備

    ハンズオン第二回では, GPU を搭載した EC2 インスタンスを起動し,深層学習モデルの学習と推論を実行する演習を行う.

    ハンズオンのソースコードは GitHub の handson/mnist に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. それ以外に必要な準備はない.

    初期状態の AWS アカウントでは, GPU 搭載の G タイプのインスタンスの起動上限が 0 になっていることがある. これを確認するには, AWS コンソールから EC2 の画面を開き,左のメニューから Limits を選択する. その中の Running On-Demand All G instances という数字が G インスタンスの起動上限を表している.

    もし,これが 0 になっていた場合は, AWS の自動申請フォームから上限緩和のリクエストを送る必要がある. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,東京 (ap-northeast-1) リージョンでは 0.71 $/hour のコストが発生する.

    AWS Educate Starter Account を使用している読者へ: 執筆時点においては, Starter Account には GPU 搭載型インスタンスを起動できないという制限が設けられている. したがって, Starter Account のユーザーはこのハンズオンを実行することはできない. 興味のある読者は,制限のない一般アカウントを自分自身で取得する必要があることに注意.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#2で作製するアプリケーションのアーキテクチャ

    図の多くの部分が,第一回ハンズオンで作成したアプリケーションと共通していることに気がつくだろう. 少しの変更で,簡単にディープラーニングを走らせる環境を構築することができるのである!主な変更点は次の3点である.

    • GPU を搭載した g4dn.xlarge インスタンスタイプを使用

    • ディープラーニングに使うプログラムがあらかじめインストールされた DLAMI (後述) を使用

    • SSH にポートフォワーディングのオプションつけてサーバーに接続し,サーバーで起動している Jupyter Notebook (後述) を使ってプログラムを書いたり実行したりする

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    python
    class Ec2ForDl(core.Stack):
    +    
    Skip to content

    Hands-on #2: AWS でディープラーニングを実践

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:3.2k
    Reading:14 min

    準備

    ハンズオン第二回では, GPU を搭載した EC2 インスタンスを起動し,深層学習モデルの学習と推論を実行する演習を行う.

    ハンズオンのソースコードは GitHub の handson/mnist に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. それ以外に必要な準備はない.

    初期状態の AWS アカウントでは, GPU 搭載の G タイプのインスタンスの起動上限が 0 になっていることがある. これを確認するには, AWS コンソールから EC2 の画面を開き,左のメニューから Limits を選択する. その中の Running On-Demand All G instances という数字が G インスタンスの起動上限を表している.

    もし,これが 0 になっていた場合は, AWS の自動申請フォームから上限緩和のリクエストを送る必要がある. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,東京 (ap-northeast-1) リージョンでは 0.71 $/hour のコストが発生する.

    AWS Educate Starter Account を使用している読者へ: 執筆時点においては, Starter Account には GPU 搭載型インスタンスを起動できないという制限が設けられている. したがって, Starter Account のユーザーはこのハンズオンを実行することはできない. 興味のある読者は,制限のない一般アカウントを自分自身で取得する必要があることに注意.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#2で作製するアプリケーションのアーキテクチャ

    図の多くの部分が,第一回ハンズオンで作成したアプリケーションと共通していることに気がつくだろう. 少しの変更で,簡単にディープラーニングを走らせる環境を構築することができるのである!主な変更点は次の3点である.

    • GPU を搭載した g4dn.xlarge インスタンスタイプを使用

    • ディープラーニングに使うプログラムがあらかじめインストールされた DLAMI (後述) を使用

    • SSH にポートフォワーディングのオプションつけてサーバーに接続し,サーバーで起動している Jupyter Notebook (後述) を使ってプログラムを書いたり実行したりする

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    python
    class Ec2ForDl(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class Ec2ForDl(core.Stack):
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class Ec2ForDl(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, (#sec_scientific_computing) ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

    • ここでは,Deep Learning 用の諸々のソフトウェアがプリンストールされた AMI (Deep Learning Amazon Machine Image; DLAMI) を選択している (第一回では,Amazon Linux という AMI を使用していた). 使用する AMI の ID は リージョンごとに指定する必要があり,ここでは us-east-1ap-northeast-1 でそれぞれ定義している.

    DLAMI という新しい概念が出てきたので,説明しよう.

    AMI が us-east-1ap-northeast-1 でしか定義されていないので,提供されているコードはこの二つのリージョンのみでデプロイ可能である. もしほかのリージョンを利用したい場合は, AMI の ID を自身で検索し,コードに書き込む必要がある.

    DLAMI (Deep Learning Amazon Machine Image)

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    最も low-level なレイヤーとしては, GPU ドライバー がインストールされている. GPU ドライバーなしには OS は GPU とコマンドのやり取りをすることができない. 次のレイヤーが CUDAcuDNN である. CUDA は, NVIDIA 社が開発した, GPU 上で汎用コンピューティングを行うための言語であり, C++ 言語を拡張したシンタックスを備える. cuDNN は CUDA で書かれたディープラーニングのライブラリであり,n 次元の畳み込みなどの演算が実装されている. ここまでが, "Base" とよばれるタイプの DLAMI の中身である.

    これに加えて, "Conda" とよばれるタイプには, "Base" のプログラム基盤の上に, TensorFlowPyTorch などのライブラリがインストールされている. さらに, Anaconda による仮想環境を使うことによって, TensorFlow の環境・ PyTorch の環境・ MxNet の環境など,フレームワークを簡単に切り替えることができる (これについては,後のハンズオンで触れる). また, Jupyter Notebook もインストール済みである.

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, (#sec_scientific_computing) ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

    • ここでは,Deep Learning 用の諸々のソフトウェアがプリンストールされた AMI (Deep Learning Amazon Machine Image; DLAMI) を選択している (第一回では,Amazon Linux という AMI を使用していた). 使用する AMI の ID は リージョンごとに指定する必要があり,ここでは us-east-1ap-northeast-1 でそれぞれ定義している.

    DLAMI という新しい概念が出てきたので,説明しよう.

    AMI が us-east-1ap-northeast-1 でしか定義されていないので,提供されているコードはこの二つのリージョンのみでデプロイ可能である. もしほかのリージョンを利用したい場合は, AMI の ID を自身で検索し,コードに書き込む必要がある.

    DLAMI (Deep Learning Amazon Machine Image)

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    最も low-level なレイヤーとしては, GPU ドライバー がインストールされている. GPU ドライバーなしには OS は GPU とコマンドのやり取りをすることができない. 次のレイヤーが CUDAcuDNN である. CUDA は, NVIDIA 社が開発した, GPU 上で汎用コンピューティングを行うための言語であり, C++ 言語を拡張したシンタックスを備える. cuDNN は CUDA で書かれたディープラーニングのライブラリであり,n 次元の畳み込みなどの演算が実装されている. ここまでが, "Base" とよばれるタイプの DLAMI の中身である.

    これに加えて, "Conda" とよばれるタイプには, "Base" のプログラム基盤の上に, TensorFlowPyTorch などのライブラリがインストールされている. さらに, Anaconda による仮想環境を使うことによって, TensorFlow の環境・ PyTorch の環境・ MxNet の環境など,フレームワークを簡単に切り替えることができる (これについては,後のハンズオンで触れる). また, Jupyter Notebook もインストール済みである.

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
     
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
     
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    SSH ログインコマンドの <IP address> 部分は自身のインスタンスの IP アドレスを代入することを忘れずに.

    本書の提供している Docker を使ってデプロイを実行した人へ

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    Jupyter Notebook とは,インタラクティブに Python のプログラムを書いたり実行したりするためのツールである. Jupyter は GUI としてウェブブラウザを介してアクセスする形式をとっており,まるでノートを書くように,プロットやテーブルのデータも美しく表示することができる (figure_title). Python に慣れている読者は,きっと一度は使ったことがあるだろう.

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    sh
    $ cd ~ # go to home directory
    -$ jupyter notebook
    $ cd ~ # go to home directory
    -$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    Jupyter Notebook の使い方 (超簡易版)

    • Shift + Enter: セルを実行

    • Esc: Command mode に遷移

    • メニューバーの "+" ボタン または Command mode で A ⇒ セルを追加

    • メニューバーの "ハサミ" ボタン または Command mode で X ⇒ セルを削除

    ショートカットの一覧などは Ventsislav Yordanov 氏によるブログ が参考になる.

    PyTorch はじめの一歩

    PyTorch は Facebook AI Research LAB (FAIR) が中心となって開発を進めている,オープンソースのディープラーニングのライブラリである. PyTorch は 有名な例で言えば Tesla 社の自動運転プロジェクトなどで使用されており,執筆時点において最も人気の高いディープラーニングライブラリの一つである. 本ハンズオンでは, PyTorch を使ってディープラーニングの実践を行う.

    PyTorch の歴史のお話

    Facebook は PyTorch のほかに Caffe2 とよばれるディープラーニングのフレームワークを開発していた (初代 Caffe は UC Berkley の博士課程学生だった Yangqing Jia によって創られた). Caffe2 は 2018 年に PyTorch プロジェクトに合併された.

    また,2019 年 12 月,日本の Preferred Networks 社が開発していた Chainer も開発を終了し,PyTorch の開発チームと協業していくことが発表された (詳しくは プレスリリース を参照). PyTorch には,開発統合前から Chainer からインスパイアされた API がいくつもあり, Chainer の DNA は今も PyTorch に引き継がれているのである…!

    本格的なディープラーニングの計算に移る前に, PyTorch ライブラリを使って, GPU で計算を行うとはどういうものか,その入り口に触れてみよう.

    まずは,新しいノートブックを作成する. Jupyter のホーム画面の右上の "New" を押し,"conda_pytorch_p36" という環境を選択したうえで,新規ノートブックを作成する (figure_title). "conda_pytorch_p36" の仮想環境には, PyTorch がインストール済みである.

    新規ノートブックの作成. "conda_pytorch_p36" の環境を選択する.

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    python
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    python
    x = torch.rand(3,3)
    -print(x)
    x = torch.rand(3,3)
    -print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    python
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    python
    z = x + y
    -print(z)
    z = x + y
    -print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    python
    z = z.to("cpu")
    -print(z)
    z = z.to("cpu")
    -print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    完成した Jupyter Notebook は /handson/mnist/pytorch/pytorch_get_started.ipynb にある. Jupyter の画面右上の "Upload" からこのファイルをアップロードして,コードを走らせることが可能である.

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    python
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    SSH ログインコマンドの <IP address> 部分は自身のインスタンスの IP アドレスを代入することを忘れずに.

    本書の提供している Docker を使ってデプロイを実行した人へ

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    Jupyter Notebook とは,インタラクティブに Python のプログラムを書いたり実行したりするためのツールである. Jupyter は GUI としてウェブブラウザを介してアクセスする形式をとっており,まるでノートを書くように,プロットやテーブルのデータも美しく表示することができる (figure_title). Python に慣れている読者は,きっと一度は使ったことがあるだろう.

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    sh
    $ cd ~ # go to home directory
    +$ jupyter notebook
    $ cd ~ # go to home directory
    +$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    Jupyter Notebook の使い方 (超簡易版)

    • Shift + Enter: セルを実行

    • Esc: Command mode に遷移

    • メニューバーの "+" ボタン または Command mode で A ⇒ セルを追加

    • メニューバーの "ハサミ" ボタン または Command mode で X ⇒ セルを削除

    ショートカットの一覧などは Ventsislav Yordanov 氏によるブログ が参考になる.

    PyTorch はじめの一歩

    PyTorch は Facebook AI Research LAB (FAIR) が中心となって開発を進めている,オープンソースのディープラーニングのライブラリである. PyTorch は 有名な例で言えば Tesla 社の自動運転プロジェクトなどで使用されており,執筆時点において最も人気の高いディープラーニングライブラリの一つである. 本ハンズオンでは, PyTorch を使ってディープラーニングの実践を行う.

    PyTorch の歴史のお話

    Facebook は PyTorch のほかに Caffe2 とよばれるディープラーニングのフレームワークを開発していた (初代 Caffe は UC Berkley の博士課程学生だった Yangqing Jia によって創られた). Caffe2 は 2018 年に PyTorch プロジェクトに合併された.

    また,2019 年 12 月,日本の Preferred Networks 社が開発していた Chainer も開発を終了し,PyTorch の開発チームと協業していくことが発表された (詳しくは プレスリリース を参照). PyTorch には,開発統合前から Chainer からインスパイアされた API がいくつもあり, Chainer の DNA は今も PyTorch に引き継がれているのである…!

    本格的なディープラーニングの計算に移る前に, PyTorch ライブラリを使って, GPU で計算を行うとはどういうものか,その入り口に触れてみよう.

    まずは,新しいノートブックを作成する. Jupyter のホーム画面の右上の "New" を押し,"conda_pytorch_p36" という環境を選択したうえで,新規ノートブックを作成する (figure_title). "conda_pytorch_p36" の仮想環境には, PyTorch がインストール済みである.

    新規ノートブックの作成. "conda_pytorch_p36" の環境を選択する.

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    python
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    python
    x = torch.rand(3,3)
    +print(x)
    x = torch.rand(3,3)
    +print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    python
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    python
    z = x + y
    +print(z)
    z = x + y
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    python
    z = z.to("cpu")
    +print(z)
    z = z.to("cpu")
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    完成した Jupyter Notebook は /handson/mnist/pytorch/pytorch_get_started.ipynb にある. Jupyter の画面右上の "Upload" からこのファイルをアップロードして,コードを走らせることが可能である.

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    python
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
     
    -%time z = torch.matmul(x,y)
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    +%time z = torch.matmul(x,y)
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
     
    -%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    python
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    +%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    python
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
     
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
     
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    このベンチマークでは, dtype=torch.float32 と指定することで,32bit の浮動小数点型を用いている. ディープラーニングの学習および推論の計算には,32bit 型,場合によっては 16bit 型が使われるのが一般的である. これの主な理由として,教師データやミニバッチに起因するノイズが,浮動小数点の精度よりも大きいことがあげられる. 32bit/16bit を採用することで,メモリー消費を抑えたり,計算速度の向上が達成できる.

    上記のベンチマークから,GPU を用いることで,約 10 倍のスピードアップを実現することができた. スピードアップの性能は,演算の種類や行列のサイズに依存する. 行列積は,そのなかでも最も速度向上が見込まれる演算の一つである.

    実践ディープラーニング! MNIST 手書き数字認識タスク

    ここまで,AWS 上でディープラーニングの計算をするための概念や前提知識をながながと説明してきたが,ついにここからディープラーニングの計算を実際に走らせてみる.

    ここでは,機械学習のタスクで最も初歩的かつ有名な MNIST データセットを使った数字認識を扱う (figure_title). これは,0 から 9 までの手書きの数字の画像が与えられ,その数字が何の数字なのかを当てる,というシンプルなタスクである.

    MNIST 手書き数字データセット

    今回は, MNIST 文字認識タスクを,畳み込みニューラルネットワーク (Convolutional Neural Network; CNN) を使って解く. ソースコードは /handson/minist/pytorch/ にある mnist.ipynbsimple_mnist.py である. なお,このプログラムは, PyTorch の公式 Example Project 集 を参考に,多少の改変を行ったものである.

    まずは,カスタムのクラスや関数が定義された simple_mnist.py をアップロードしよう (figure_title). 画面右上の "Upload" ボタンをクリックし,ファイルを選択することでアップロードができる. この Python プログラムの中に,CNN のモデルや,学習の各イテレーションにおけるパラメータの更新などが記述されている. 今回はこの中身を説明することはしないが,興味のある読者は自身でソースコードを読んでみるとよい.

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    python
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    このベンチマークでは, dtype=torch.float32 と指定することで,32bit の浮動小数点型を用いている. ディープラーニングの学習および推論の計算には,32bit 型,場合によっては 16bit 型が使われるのが一般的である. これの主な理由として,教師データやミニバッチに起因するノイズが,浮動小数点の精度よりも大きいことがあげられる. 32bit/16bit を採用することで,メモリー消費を抑えたり,計算速度の向上が達成できる.

    上記のベンチマークから,GPU を用いることで,約 10 倍のスピードアップを実現することができた. スピードアップの性能は,演算の種類や行列のサイズに依存する. 行列積は,そのなかでも最も速度向上が見込まれる演算の一つである.

    実践ディープラーニング! MNIST 手書き数字認識タスク

    ここまで,AWS 上でディープラーニングの計算をするための概念や前提知識をながながと説明してきたが,ついにここからディープラーニングの計算を実際に走らせてみる.

    ここでは,機械学習のタスクで最も初歩的かつ有名な MNIST データセットを使った数字認識を扱う (figure_title). これは,0 から 9 までの手書きの数字の画像が与えられ,その数字が何の数字なのかを当てる,というシンプルなタスクである.

    MNIST 手書き数字データセット

    今回は, MNIST 文字認識タスクを,畳み込みニューラルネットワーク (Convolutional Neural Network; CNN) を使って解く. ソースコードは /handson/minist/pytorch/ にある mnist.ipynbsimple_mnist.py である. なお,このプログラムは, PyTorch の公式 Example Project 集 を参考に,多少の改変を行ったものである.

    まずは,カスタムのクラスや関数が定義された simple_mnist.py をアップロードしよう (figure_title). 画面右上の "Upload" ボタンをクリックし,ファイルを選択することでアップロードができる. この Python プログラムの中に,CNN のモデルや,学習の各イテレーションにおけるパラメータの更新などが記述されている. 今回はこの中身を説明することはしないが,興味のある読者は自身でソースコードを読んでみるとよい.

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    python
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
     
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
     
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    python
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    python
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
     
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
     
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
     
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
     
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    python
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    python
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
     
    -print("Example data size:", example_data.shape)
    +print("Example data size:", example_data.shape)
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
     
    -print("Example data size:", example_data.shape)
    +print("Example data size:", example_data.shape)
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    python
    model = Model()
    -model.to("cuda") # load to GPU
    model = Model()
    -model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    python
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    python
    model = Model()
    +model.to("cuda") # load to GPU
    model = Model()
    +model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    python
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
     
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
     
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    python
    model.eval()
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    python
    model.eval()
     
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    model.eval()
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    model.eval()
     
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は (#handson_01_delete_stack) 参照).

    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    - +fig = plt.figure(figsize=(10,4)) +for i in range(10): + plt.subplot(2,5,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], cmap='gray', interpolation='none') + plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item())) + plt.xticks([]) + plt.yticks([]) +plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は (#handson_01_delete_stack) 参照).

    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    + \ No newline at end of file diff --git a/development/aws/handson-qabot.html b/development/aws/handson-qabot.html index 33d6f667..a7f49f73 100644 --- a/development/aws/handson-qabot.html +++ b/development/aws/handson-qabot.html @@ -5,16 +5,16 @@ Hands-on #3: AWS で自動質問回答ボットを走らせる | Toshiki's Note - + - + - + - + @@ -37,179 +37,179 @@ -
    Skip to content

    Hands-on #3: AWS で自動質問回答ボットを走らせる

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:2.5k
    Reading:11 min

    ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.

    通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 ( (#sec_aws_batch)) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.

    Fargate

    ハンズオンに入っていく前に, Fargate という AWS の機能を知っておく必要がある (figure_title).

    Fargate のアイコン

    ECS の概要を示した (#ecs_overview) をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. EC2 あるいは Fargate のいずれかである. EC2 を用いた場合は,先の章 ( (#sec_first_ec2), (#sec_jupyter_and_deep_learning)) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 ( (#sec_aws_batch)) で説明することにする.

    Fargate とは, ECS での利用に特化して設計された,コンテナを使用した計算タスクを走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は docker run のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.

    Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは 公式ドキュメンテーション "Amazon ECS on AWS Fargate" 参照). クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.

    以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.

    厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.

    準備

    ハンズオンのソースコードは GitHub の handson/qa-bot にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    answer: 1921
    -

    人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

    今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    json
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    sh
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    出力:

    json
    {
    -    "score": 0.5235594527494207,
    -    "start": 470,
    -    "end": 506,
    -    "answer": "his services to theoretical physics,"
    -}
    {
    -    "score": 0.5235594527494207,
    -    "start": 470,
    -    "end": 506,
    -    "answer": "his services to theoretical physics,"
    -}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    今回提供する Q-A ボットの Docker のソースコードは https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile にある.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,以下のような設計である.

    • クライアントは,質問を AWS 上のアプリケーションに送信する.

    • 質問のタスクは ECS によって処理される.

    • ECS は, Docker Hub から,イメージをダウンロードする.

    • 次に,ECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.

      • このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.
    • ジョブが実行される.

    • ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.

    • 最後に,クライアントは DynamoDB から質問への回答を読み取る.

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    python
    class EcsClusterQaBot(core.Stack):
    +    
    Skip to content

    Hands-on #3: AWS で自動質問回答ボットを走らせる

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:2.5k
    Reading:11 min

    ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.

    通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 ( (#sec_aws_batch)) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.

    Fargate

    ハンズオンに入っていく前に, Fargate という AWS の機能を知っておく必要がある (figure_title).

    Fargate のアイコン

    ECS の概要を示した (#ecs_overview) をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. EC2 あるいは Fargate のいずれかである. EC2 を用いた場合は,先の章 ( (#sec_first_ec2), (#sec_jupyter_and_deep_learning)) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 ( (#sec_aws_batch)) で説明することにする.

    Fargate とは, ECS での利用に特化して設計された,コンテナを使用した計算タスクを走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は docker run のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.

    Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは 公式ドキュメンテーション "Amazon ECS on AWS Fargate" 参照). クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.

    以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.

    厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.

    準備

    ハンズオンのソースコードは GitHub の handson/qa-bot にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 ( (#handson_01_prep)) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    answer: 1921
    +

    人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

    今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    json
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    sh
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    出力:

    json
    {
    +    "score": 0.5235594527494207,
    +    "start": 470,
    +    "end": 506,
    +    "answer": "his services to theoretical physics,"
    +}
    {
    +    "score": 0.5235594527494207,
    +    "start": 470,
    +    "end": 506,
    +    "answer": "his services to theoretical physics,"
    +}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    今回提供する Q-A ボットの Docker のソースコードは https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile にある.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,以下のような設計である.

    • クライアントは,質問を AWS 上のアプリケーションに送信する.

    • 質問のタスクは ECS によって処理される.

    • ECS は, Docker Hub から,イメージをダウンロードする.

    • 次に,ECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.

      • このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.
    • ジョブが実行される.

    • ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.

    • 最後に,クライアントは DynamoDB から質問への回答を読み取る.

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    python
    class EcsClusterQaBot(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
     
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
     
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
     
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
     
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    class EcsClusterQaBot(core.Stack):
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    class EcsClusterQaBot(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
     
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
     
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
     
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
     
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

    • ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.

    • ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.

    • ここで,実行するタスクを定義している (task definition).

    • ここで, タスクの実行で使用する Docker イメージを定義している.

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    python
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

    • ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.

    • ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.

    • ここで,実行するタスクを定義している (task definition).

    • ここで, タスクの実行で使用する Docker イメージを定義している.

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    python
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
     
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
     
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
     
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
     
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.

    このコードで cpu=1024 と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は 公式ドキュメンテーション "Amazon ECS on AWS Fargate" を参照のこと.

    CPU ユニットと 指定可能なメモリー量の換算表

    CPU ユニット

    メモリーの値

    256 (.25 vCPU)

    0.5 GB, 1 GB, 2 GB

    512 (.5 vCPU)

    1 GB, 2 GB, 3 GB, 4 GB

    1024 (1 vCPU)

    2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB

    2048 (2 vCPU)

    Between 4 GB and 16 GB in 1-GB increments

    4096 (4 vCPU)

    Between 8 GB and 30 GB in 1-GB increments

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.

    このコードで cpu=1024 と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は 公式ドキュメンテーション "Amazon ECS on AWS Fargate" を参照のこと.

    CPU ユニットと 指定可能なメモリー量の換算表

    CPU ユニット

    メモリーの値

    256 (.25 vCPU)

    0.5 GB, 1 GB, 2 GB

    512 (.5 vCPU)

    1 GB, 2 GB, 3 GB, 4 GB

    1024 (1 vCPU)

    2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB

    2048 (2 vCPU)

    Between 4 GB and 16 GB in 1-GB increments

    4096 (4 vCPU)

    Between 8 GB and 30 GB in 1-GB increments

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. figure_title で, FARGATE という文字の下に 0 Running tasks, 0 Pending tasks と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.

    ECS コンソール画面

    続いて,この画面の左のメニューバーから Task Definitions という項目を見つけ,クリックしよう. 移動した先のページで EcsClusterQaBotEcsClusterQaBotTaskDefXXXX という項目が見つかるので,開く. 開いた先のページをスクロールすると figure_title に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.

    Task definition の確認

    タスクの実行

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, "Tasks" という名前のタブがあるので,それを開く (figure_title). すると,実行中のタスクの一覧が表示されるだろう.

    ECS のタスクの実行状況をモニタリング

    figure_title で見て取れるように, "Last status = Pending" となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.

    しばらく待つうちに, Status が "RUNNING" に遷移し,計算が始まる. 計算が終わると, Status は "STOPPED" に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.

    figure_title の画面から, "Task" の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (figure_title). "Last status", "Platform version" など,タスクの情報が表示されている. また, "Logs" のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.

    質問タスクの実行結果

    さて, run_task.py を実行したコマンドラインに戻ってきてみると, figure_title のような出力が得られているはずである. "Momotaro" という正しい回答が返ってきている!

    質問タスクの実行結果

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    sh
    $ cdk destroy
    $ cdk destroy
    - +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. figure_title で, FARGATE という文字の下に 0 Running tasks, 0 Pending tasks と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.

    ECS コンソール画面

    続いて,この画面の左のメニューバーから Task Definitions という項目を見つけ,クリックしよう. 移動した先のページで EcsClusterQaBotEcsClusterQaBotTaskDefXXXX という項目が見つかるので,開く. 開いた先のページをスクロールすると figure_title に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.

    Task definition の確認

    タスクの実行

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, "Tasks" という名前のタブがあるので,それを開く (figure_title). すると,実行中のタスクの一覧が表示されるだろう.

    ECS のタスクの実行状況をモニタリング

    figure_title で見て取れるように, "Last status = Pending" となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.

    しばらく待つうちに, Status が "RUNNING" に遷移し,計算が始まる. 計算が終わると, Status は "STOPPED" に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.

    figure_title の画面から, "Task" の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (figure_title). "Last status", "Platform version" など,タスクの情報が表示されている. また, "Logs" のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.

    質問タスクの実行結果

    さて, run_task.py を実行したコマンドラインに戻ってきてみると, figure_title のような出力が得られているはずである. "Momotaro" という正しい回答が返ってきている!

    質問タスクの実行結果

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    sh
    $ cdk destroy
    $ cdk destroy
    + \ No newline at end of file diff --git a/development/aws/handson-serverless.html b/development/aws/handson-serverless.html index 568b8319..64ad94c0 100644 --- a/development/aws/handson-serverless.html +++ b/development/aws/handson-serverless.html @@ -5,16 +5,16 @@ Hands-on #5: サーバーレス入門 | Toshiki's Note - + - + - + - + @@ -37,226 +37,226 @@ -
    Skip to content

    Hands-on #5: サーバーレス入門

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:2.4k
    Reading:10 min

    前章ではサーバーレスアーキテクチャの概要の説明を行った. 本章では,ハンズオン形式でサーバーレスクラウドを実際に動かしながら,具体的な使用方法を学んでいこう. 今回のハンズオンでは Lambda, S3, DynamoDB の三つのサーバーレスクラウドの構成要素に触れていく. それぞれについて,短いチュートリアルを用意してある.

    Lambda ハンズオン

    まずは, Lambda を実際に動かしてみよう. ハンズオンのソースコードは GitHub の handson/serverless/lambda に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して Python で書かれたコードを Lambda に登録する. 続いて STEP 2 では, Invoke API を使用して,同時にいくつもの Lambda を起動し,並列な計算を行う. Lambda のワークフローを体験する目的で最小限の設定である.

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    +    
    Skip to content

    Hands-on #5: サーバーレス入門

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:2.4k
    Reading:10 min

    前章ではサーバーレスアーキテクチャの概要の説明を行った. 本章では,ハンズオン形式でサーバーレスクラウドを実際に動かしながら,具体的な使用方法を学んでいこう. 今回のハンズオンでは Lambda, S3, DynamoDB の三つのサーバーレスクラウドの構成要素に触れていく. それぞれについて,短いチュートリアルを用意してある.

    Lambda ハンズオン

    まずは, Lambda を実際に動かしてみよう. ハンズオンのソースコードは GitHub の handson/serverless/lambda に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して Python で書かれたコードを Lambda に登録する. 続いて STEP 2 では, Invoke API を使用して,同時にいくつもの Lambda を起動し,並列な計算を行う. Lambda のワークフローを体験する目的で最小限の設定である.

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
     
    -class SimpleLambda(core.Stack):
    +class SimpleLambda(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
     
    -class SimpleLambda(core.Stack):
    +class SimpleLambda(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

    • 次に, Lambda に <1> で書いた関数を配置している. パラメータの意味は,文字どおりの意味なので難しくはないが,以下に解説する.

      • runtime=_lambda.Runtime.PYTHON_3_7: ここでは, Python3.7 を使って上記で定義された関数を実行せよ,と指定している. Python3.7 のほかに, Node.js, Java, Ruby, Go などの言語を指定することが可能である.

      • code=_lambda.Code.from_inline(FUNC): 実行されるべき関数が書かれたコードを指定する. ここでは, FUNC=... で定義した文字列を渡しているが,文字列以外にもファイルのパスを渡すことも可能である.

      • handler="index.handler": これは,コードの中にいくつかのサブ関数が含まれているときに,メインとサブを区別するためのパラメータである. handler という名前の関数をメイン関数として実行せよ,という意味である.

      • memory_size=128: メモリーは 128MB を最大で使用することを指定している.

      • timeout=core.Duration.seconds(10) タイムアウト時間を 10 秒に設定している. 10 秒以内に関数の実行が終了しなかった場合,エラーが返される.

      • dead_letter_queue_enabled=True: アドバンストな設定なので説明は省略する.

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

    • 次に, Lambda に <1> で書いた関数を配置している. パラメータの意味は,文字どおりの意味なので難しくはないが,以下に解説する.

      • runtime=_lambda.Runtime.PYTHON_3_7: ここでは, Python3.7 を使って上記で定義された関数を実行せよ,と指定している. Python3.7 のほかに, Node.js, Java, Ruby, Go などの言語を指定することが可能である.

      • code=_lambda.Code.from_inline(FUNC): 実行されるべき関数が書かれたコードを指定する. ここでは, FUNC=... で定義した文字列を渡しているが,文字列以外にもファイルのパスを渡すことも可能である.

      • handler="index.handler": これは,コードの中にいくつかのサブ関数が含まれているときに,メインとサブを区別するためのパラメータである. handler という名前の関数をメイン関数として実行せよ,という意味である.

      • memory_size=128: メモリーは 128MB を最大で使用することを指定している.

      • timeout=core.Duration.seconds(10) タイムアウト時間を 10 秒に設定している. 10 秒以内に関数の実行が終了しなかった場合,エラーが返される.

      • dead_letter_queue_enabled=True: アドバンストな設定なので説明は省略する.

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    Lambda コンソール - 関数の一覧

    今回のアプリケーションで作成したのが SimpleLambda で始まるランダムな名前のついた関数だ. 関数の名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. 先ほどプログラムの中で定義した Python の関数がエディターから確認できる. さらに下の方にスクロールすると,関数の各種設定も確認できる.

    Lambda コンソール - 関数の詳細

    Lambda で実行されるコードは, Lambda のコンソール画面 (figure_title) のエディターで編集することもできる. デバッグをするときなどは,こちらを直接いじる方が早い場合もある. その場合は, CDK のコードに行った編集を反映させなおすことを忘れずに.

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    sh
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    ....................................................................................................
    -Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    figure_title で "Invocations" が関数が何度実行されたかを意味している. たしかに 100 回実行されていることがわかる. さらに, "Concurrent executions" は何個のタスクが同時に行われたかを示している. ここでは 96 となっていることから,96 個のタスクが並列的に実行されたことを意味している (これが 100 とならないのは,タスクの開始のコマンドが送られたのが完全には同タイミングではないことに起因する).

    このように,非常にシンプルではあるが, Lambda を使うことで,同時並列的に処理を実行することのできるクラウドシステムを簡単に作ることができた.

    もしこのようなことを従来的な serverful なクラウドで行おうとした場合,クラスターのスケーリングなど多くのコードを書くことに加えて,いろいろなパラメータを調節する必要がある.

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    Lambda コンソール - 関数の一覧

    今回のアプリケーションで作成したのが SimpleLambda で始まるランダムな名前のついた関数だ. 関数の名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. 先ほどプログラムの中で定義した Python の関数がエディターから確認できる. さらに下の方にスクロールすると,関数の各種設定も確認できる.

    Lambda コンソール - 関数の詳細

    Lambda で実行されるコードは, Lambda のコンソール画面 (figure_title) のエディターで編集することもできる. デバッグをするときなどは,こちらを直接いじる方が早い場合もある. その場合は, CDK のコードに行った編集を反映させなおすことを忘れずに.

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    sh
    ....................................................................................................
    +Submitted 100 tasks to Lambda!
    ....................................................................................................
    +Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    figure_title で "Invocations" が関数が何度実行されたかを意味している. たしかに 100 回実行されていることがわかる. さらに, "Concurrent executions" は何個のタスクが同時に行われたかを示している. ここでは 96 となっていることから,96 個のタスクが並列的に実行されたことを意味している (これが 100 とならないのは,タスクの開始のコマンドが送られたのが完全には同タイミングではないことに起因する).

    このように,非常にシンプルではあるが, Lambda を使うことで,同時並列的に処理を実行することのできるクラウドシステムを簡単に作ることができた.

    もしこのようなことを従来的な serverful なクラウドで行おうとした場合,クラスターのスケーリングなど多くのコードを書くことに加えて,いろいろなパラメータを調節する必要がある.

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • partition_key: すべての DynamoDB テーブルには Partition key が定義されていなければならない. Partition key とは,テーブル内の要素 (レコード) ごとに存在する固有の ID のことである. 同一の Partition key をもった要素がテーブルの中に二つ以上存在することはできない (注: Sort Key を使用している場合は除く.詳しくは 公式ドキュメンテーション "Core Components of Amazon DynamoDB" 参照). また, Partition key が定義されていない要素はテーブルの中に存在することはできない. ここでは, Partition key に item_id という名前をつけている.

    • billing_mode: ddb.BillingMode.PAY_PER_REQUEST を指定することで, On-demand Capacity Mode の DynamoDB が作成される. ほかに PROVISIONED というモードがあるが,これはかなり高度なケースを除いて使用しないだろう.

    • removal_policy: CloudFormation のスタックが消去されたときに, DynamoDB も一緒に消去されるかどうかを指定する. このコードでは DESTROY を選んでいるので,すべて消去される. ほかのオプションを選択すると,スタックを消去しても DynamoDB のバックアップを残す,などの動作を定義することができる.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • partition_key: すべての DynamoDB テーブルには Partition key が定義されていなければならない. Partition key とは,テーブル内の要素 (レコード) ごとに存在する固有の ID のことである. 同一の Partition key をもった要素がテーブルの中に二つ以上存在することはできない (注: Sort Key を使用している場合は除く.詳しくは 公式ドキュメンテーション "Core Components of Amazon DynamoDB" 参照). また, Partition key が定義されていない要素はテーブルの中に存在することはできない. ここでは, Partition key に item_id という名前をつけている.

    • billing_mode: ddb.BillingMode.PAY_PER_REQUEST を指定することで, On-demand Capacity Mode の DynamoDB が作成される. ほかに PROVISIONED というモードがあるが,これはかなり高度なケースを除いて使用しないだろう.

    • removal_policy: CloudFormation のスタックが消去されたときに, DynamoDB も一緒に消去されるかどうかを指定する. このコードでは DESTROY を選んでいるので,すべて消去される. ほかのオプションを選択すると,スタックを消去しても DynamoDB のバックアップを残す,などの動作を定義することができる.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    DynamoDB のコンソール (テーブルの一覧)

    今回のアプリケーションで作成したのが SimpleDynamoDb で始まるランダムな名前のついたテーブルだ. テーブルの名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. "Items" のタブをクリックすると,テーブルの中のレコードを確認できる. 現時点ではなにもデータを書き込んでいないので,空である.

    DynamoDB のコンソール (テーブルの詳細画面)

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    python
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    DynamoDB のコンソール (テーブルの一覧)

    今回のアプリケーションで作成したのが SimpleDynamoDb で始まるランダムな名前のついたテーブルだ. テーブルの名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. "Items" のタブをクリックすると,テーブルの中のレコードを確認できる. 現時点ではなにもデータを書き込んでいないので,空である.

    DynamoDB のコンソール (テーブルの詳細画面)

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    python
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
     
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
     
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    python
    import boto3
    -ddb = boto3.resource('dynamodb')
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    python
    import boto3
    +ddb = boto3.resource('dynamodb')
     
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    import boto3
    -ddb = boto3.resource('dynamodb')
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)
    import boto3
    +ddb = boto3.resource('dynamodb')
     
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    python
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    +# デプロイを実行
    +$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    python
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if key is None:
    -        key = os.path.basename(filename)
    +    if key is None:
    +        key = os.path.basename(filename)
     
    -    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    +    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if key is None:
    -        key = os.path.basename(filename)
    +    if key is None:
    +        key = os.path.basename(filename)
     
    -    bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    python
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    +    bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    python
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if filename is None:
    -        filename = os.path.basename(key)
    +    if filename is None:
    +        filename = os.path.basename(key)
     
    -    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    +    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if filename is None:
    -        filename = os.path.basename(key)
    +    if filename is None:
    +        filename = os.path.basename(key)
     
    -    bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy
    - + bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy
    + \ No newline at end of file diff --git a/development/aws/index.html b/development/aws/index.html index b1baf647..5434ddb3 100644 --- a/development/aws/index.html +++ b/development/aws/index.html @@ -5,16 +5,16 @@ はじめに | Toshiki's Note - + - + - + - + @@ -37,8 +37,8 @@ -
    Skip to content

    はじめに

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:1.3k
    Reading:4 min

    本書の目的・内容

    本書は,東京大学計数工学科で 2021 年度 S1/S2 タームに開講されている"システム情報工学特論"の講義資料として作成された.

    本書の目的は,クラウドの初心者を対象とし,クラウドの基礎的な知識・概念を解説する. また, Amazon Web Services (以下, AWS) の提供するクラウド環境を実例として,具体的なクラウドの利用方法をハンズオンを通して学ぶ.

    とくに,科学・エンジニアリングの学生を対象として,研究などの目的でクラウドを利用するための実践的な手順を紹介する. 知識・理論の説明は最小限に留め,実践を行う中で必要な概念の解説を行う予定である. 読者が今後,研究などでクラウドを利用する際の,足がかりとなれば本書の目的は十分達成されたことになる.

    本書は以下のような三部構成になっている.

    本書の構成
    テーマハンズオン

    第一部 (1章-4章)

    クラウドの基礎

    • AWSに自分のサーバーを立ち上げる

    第二部 (5章-9章)

    クラウドを活用した機械学習

    • AWS と Jupyter を使って始めるディープラーニング

    • スケーラブルな自動質問回答ボットを作る

    • 並列化されたハイパーパラメータサーチの実装

    第三部 (10章-13章)

    サーバーレスアーキテクチャ入門

    • Lambda, DynamoDB, S3 の演習

    • 俳句を投稿する SNS "Bashoutter" を作る

    第一部は,クラウドの基礎となる概念・知識を解説する. セキュリティやネットワークなど,クラウドを利用する上で最低限おさえなければいけないポイントを説明する. ハンズオンでは,はじめての仮想サーバーを AWS に立ち上げる演習を行う.

    第二部では,クラウド上で科学計算 (とくに機械学習) を走らせるための入門となる知識・技術を解説する. あわせて, Docker とよばれる仮想計算環境の使用方法を紹介する. 一つ目のハンズオンでは, AWS のクラウドで Jupyter Notebook を起動し簡単な機械学習の計算を走らせる課題を実践する. 二つ目のハンズオンでは,深層学習を用いた自然言語処理により,質問に自動で回答を生成するボットを作成する. 最後に,複数台の GPU インスタンスからなるクラスターを起動し,並列に深層学習のハイパーパラメータサーチを行う方法を紹介する.

    第三部では,サーバーレスアーキテクチャとよばれる最新のクラウドのアーキテクチャを紹介する. これは,サーバーの処理能力を負荷に応じてより柔軟に拡大・縮小するための概念であり,それ以前 (Serverful としばしばよばれる) と質的に異なる設計思想をクラウドに導入するものである. ハンズオンでは,サーバーレスクラウドの主要なコンポーネントである Lambda, DynamoDB, S3 の演習を提供する. さらに,サーバーレスの技術を使用して簡単な SNS をクラウド上に作成する.

    これらの豊富なハンズオンにより, AWS 上にクラウドシステムを開発するための知識と技術が身につくはずである. いずれのハンズオンも,実用性を重視したものになっており,これらをベースにカスタマイズを施すことで様々な応用が可能である.

    本書のフィロソフィー

    本書のフィロソフィーを一言で表すなら, "ロケットで宇宙まで飛んでいって一度地球を眺めてみよう!" である.

    どういうことか?

    ここでいう"地球"とは,クラウドコンピューティングの全体像のことである. 言うまでもなく,クラウドという技術は非常に広範かつ複雑な概念で,幾多の情報技術・ハードウェア・アルゴリズムが精緻に組み合わさってできた総体である. そして,今日では科学研究から日常のインフラ設備に至るまで,我々の社会の多くの部分がクラウド技術によって支えられている.

    ここでいう"ロケット"とはこの講義のことである. この講義では,ロケットに乗って宇宙まで飛び立ち,地球(クラウド)の全体を自身の目で眺めてもらう. その際,ロケットの成り立ちや仕組み (背後にある要素技術やプログラムのソースコード) を深くは問わない. 将来,自分が研究などの目的でクラウドを利用することになった際に,改めて学んでもらえば良い. 本書の目的はむしろ,クラウドの最先端に実際に触れ,そこからどんな景色が見えるか(どんな応用が可能か)を実感してもらうことである.

    そのような理由で,本書はクラウドの基礎から応用まで幅広いテーマを取り扱う. 第一部はクラウドの基礎から始め,第二部では一気にレベルアップし機械学習(深層学習)をクラウドで実行する手法を解説する. さらに第三部では,サーバーレス・アーキテクチャというここ数年のうちに確立した全く新しいクラウドの設計について解説する. それぞれで本一冊分以上の内容に相当するものであるが,本書はあえてこれらを一冊にまとめ連続的に俯瞰するという野心的な意図をもって執筆された.

    決して楽な搭乗体験ではないかもしれないが,このロケットにしがみついてきてもらえれば,とてもエキサイティングな景色が見られることを約束したい.

    宇宙からみた地球 (Image from NASA https://www.nasa.gov/image-feature/planet-of-clouds)

    AWS アカウント

    本書では,ハンズオン形式で AWS のクラウドを実際に動かす演習を提供する. 自分でハンズオンを実行してみたい読者は,各自で AWS のアカウントの作成をしていただく. AWS のアカウントの作成の仕方は巻末付録 ( (#sec:create_aws_account)) に簡単に記載したので,必要に応じて参照していただきたい.

    AWS にはいくつかの機能に対して無料利用枠が設定されており,いくつかのハンズオンは無料の範囲内で実行できる. 一方,ほかのハンズオン (とくに機械学習を扱うもの) では数ドル程度のコストが発生する. ハンズオンごとに発生するおおよそのコストについて記述があるので,注意をしながらハンズオンに取り組んでいただきたい.

    また,大学などの教育機関における講義で AWS を使用する際は, AWS Educate というプログラムを利用することも可能である. これは,講義の担当者が申請を行うことで,受講する学生に対し AWS クレジットが提供されるというプログラムである. AWS Educate を利用することで金銭的な負担なしに AWS を体験することができる. また,講義を経由せず個人でも AWS Educate に参加することも可能である. AWS Educate からは様々な学習教材が提供されているので,ぜひ活用してもらいたい.

    環境構築

    本書では, AWS 上にクラウドアプリケーションを展開するハンズオンを実施する. そこで紹介するプログラムを実行するためには,以下の計算機環境が必要である. インストールの方法については,巻末付録 ( (#sec:appendix_settingup)) に記してある. 必要に応じて参照し,環境構築を各自実施していただきたい.

    • UNIX 系コンソール: ハンズオンで紹介するコマンドを実行したり, SSH でサーバーにアクセスするため, UNIX 系のコンソール環境が必要である. Mac または Linux のユーザーは, OS に標準搭載のコンソール(ターミナルとも呼ばれる)を使用すればよい. Windows のユーザーは, Windows Subsystem for Linux (WSL) を使い, Linux の仮想環境のインストールを推奨する ( (#sec:install_wsl) 参照).

    • Docker: 本書では Docker とよばれる仮想計算環境の利用方法を解説する. インストール手順については (#sec:install_docker) を参照のこと.

    • Python: Version 3.6 以上をインストールする. とくに,ハンズオンでは venv モジュールを使用する. venv の使い方は (#venv_quick_guide) 参照のこと.

    • Node.js: version 12.0 以上 をインストールする.

    • AWS CLI: Version 2 をインストールする. インストール手順については (#aws_cli_install) 参照のこと.

    • AWS CDK: Version 1.100 以上をインストールする. Version 2 以降には未対応である. インストール手順については (#aws_cdk_install) 参照のこと.

    • AWS 認証鍵の設定: AWS API をコマンドラインから呼ぶには,認証鍵 (secret key) が設定されている必要がある. 認証鍵の設定については (#aws_cli_install) 参照のこと.

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は (#sec_handson_docker) に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    • Python の基本的な理解: 本書では Python を使ってプログラムの作成を行う. 使用するライブラリは十分抽象化されており,関数の名前を見ただけで意味が明瞭なものがほとんどであるので, Python に詳しくなくても心配する必要はない.

    • Linux コマンドラインの基礎的な理解: クラウドを利用する際,クラウド上に立ち上がるサーバーは基本的に Linux である. Linux のコマンドラインについて知識があると,トラブルシュートなどが容易になる. 筆者のおすすめの参考書は The Linux Command Line by William Shotts である. ウェブで無料で読むことができるので,読んだことのない人はぜひ一読を.

    講義に関連する資料

    ハンズオンで使うプログラムや教科書のソースコードは以下のウェブページで公開している.

    本書で使用するノーテーションなど

    • コードやシェルのコマンドは monospace letter で記述する.

    • シェルに入力するコマンドは,それがシェルコマンドであると明示する目的で,先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力には $ はついていない点に留意する.

    また,以下のような形式で注意やチップスを提供する.

    追加のコメントなどを記す.

    発展的な議論やアイディアなどを紹介する.

    陥りやすいミスなどの注意事項を述べる.

    絶対に犯してはならないミスを指摘する.

    - +
    Skip to content

    はじめに

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:1.3k
    Reading:4 min

    本書の目的・内容

    本書は,東京大学計数工学科で 2021 年度 S1/S2 タームに開講されている"システム情報工学特論"の講義資料として作成された.

    本書の目的は,クラウドの初心者を対象とし,クラウドの基礎的な知識・概念を解説する. また, Amazon Web Services (以下, AWS) の提供するクラウド環境を実例として,具体的なクラウドの利用方法をハンズオンを通して学ぶ.

    とくに,科学・エンジニアリングの学生を対象として,研究などの目的でクラウドを利用するための実践的な手順を紹介する. 知識・理論の説明は最小限に留め,実践を行う中で必要な概念の解説を行う予定である. 読者が今後,研究などでクラウドを利用する際の,足がかりとなれば本書の目的は十分達成されたことになる.

    本書は以下のような三部構成になっている.

    本書の構成
    テーマハンズオン

    第一部 (1章-4章)

    クラウドの基礎

    • AWSに自分のサーバーを立ち上げる

    第二部 (5章-9章)

    クラウドを活用した機械学習

    • AWS と Jupyter を使って始めるディープラーニング

    • スケーラブルな自動質問回答ボットを作る

    • 並列化されたハイパーパラメータサーチの実装

    第三部 (10章-13章)

    サーバーレスアーキテクチャ入門

    • Lambda, DynamoDB, S3 の演習

    • 俳句を投稿する SNS "Bashoutter" を作る

    第一部は,クラウドの基礎となる概念・知識を解説する. セキュリティやネットワークなど,クラウドを利用する上で最低限おさえなければいけないポイントを説明する. ハンズオンでは,はじめての仮想サーバーを AWS に立ち上げる演習を行う.

    第二部では,クラウド上で科学計算 (とくに機械学習) を走らせるための入門となる知識・技術を解説する. あわせて, Docker とよばれる仮想計算環境の使用方法を紹介する. 一つ目のハンズオンでは, AWS のクラウドで Jupyter Notebook を起動し簡単な機械学習の計算を走らせる課題を実践する. 二つ目のハンズオンでは,深層学習を用いた自然言語処理により,質問に自動で回答を生成するボットを作成する. 最後に,複数台の GPU インスタンスからなるクラスターを起動し,並列に深層学習のハイパーパラメータサーチを行う方法を紹介する.

    第三部では,サーバーレスアーキテクチャとよばれる最新のクラウドのアーキテクチャを紹介する. これは,サーバーの処理能力を負荷に応じてより柔軟に拡大・縮小するための概念であり,それ以前 (Serverful としばしばよばれる) と質的に異なる設計思想をクラウドに導入するものである. ハンズオンでは,サーバーレスクラウドの主要なコンポーネントである Lambda, DynamoDB, S3 の演習を提供する. さらに,サーバーレスの技術を使用して簡単な SNS をクラウド上に作成する.

    これらの豊富なハンズオンにより, AWS 上にクラウドシステムを開発するための知識と技術が身につくはずである. いずれのハンズオンも,実用性を重視したものになっており,これらをベースにカスタマイズを施すことで様々な応用が可能である.

    本書のフィロソフィー

    本書のフィロソフィーを一言で表すなら, "ロケットで宇宙まで飛んでいって一度地球を眺めてみよう!" である.

    どういうことか?

    ここでいう"地球"とは,クラウドコンピューティングの全体像のことである. 言うまでもなく,クラウドという技術は非常に広範かつ複雑な概念で,幾多の情報技術・ハードウェア・アルゴリズムが精緻に組み合わさってできた総体である. そして,今日では科学研究から日常のインフラ設備に至るまで,我々の社会の多くの部分がクラウド技術によって支えられている.

    ここでいう"ロケット"とはこの講義のことである. この講義では,ロケットに乗って宇宙まで飛び立ち,地球(クラウド)の全体を自身の目で眺めてもらう. その際,ロケットの成り立ちや仕組み (背後にある要素技術やプログラムのソースコード) を深くは問わない. 将来,自分が研究などの目的でクラウドを利用することになった際に,改めて学んでもらえば良い. 本書の目的はむしろ,クラウドの最先端に実際に触れ,そこからどんな景色が見えるか(どんな応用が可能か)を実感してもらうことである.

    そのような理由で,本書はクラウドの基礎から応用まで幅広いテーマを取り扱う. 第一部はクラウドの基礎から始め,第二部では一気にレベルアップし機械学習(深層学習)をクラウドで実行する手法を解説する. さらに第三部では,サーバーレス・アーキテクチャというここ数年のうちに確立した全く新しいクラウドの設計について解説する. それぞれで本一冊分以上の内容に相当するものであるが,本書はあえてこれらを一冊にまとめ連続的に俯瞰するという野心的な意図をもって執筆された.

    決して楽な搭乗体験ではないかもしれないが,このロケットにしがみついてきてもらえれば,とてもエキサイティングな景色が見られることを約束したい.

    宇宙からみた地球 (Image from NASA https://www.nasa.gov/image-feature/planet-of-clouds)

    AWS アカウント

    本書では,ハンズオン形式で AWS のクラウドを実際に動かす演習を提供する. 自分でハンズオンを実行してみたい読者は,各自で AWS のアカウントの作成をしていただく. AWS のアカウントの作成の仕方は巻末付録 ( (#sec:create_aws_account)) に簡単に記載したので,必要に応じて参照していただきたい.

    AWS にはいくつかの機能に対して無料利用枠が設定されており,いくつかのハンズオンは無料の範囲内で実行できる. 一方,ほかのハンズオン (とくに機械学習を扱うもの) では数ドル程度のコストが発生する. ハンズオンごとに発生するおおよそのコストについて記述があるので,注意をしながらハンズオンに取り組んでいただきたい.

    また,大学などの教育機関における講義で AWS を使用する際は, AWS Educate というプログラムを利用することも可能である. これは,講義の担当者が申請を行うことで,受講する学生に対し AWS クレジットが提供されるというプログラムである. AWS Educate を利用することで金銭的な負担なしに AWS を体験することができる. また,講義を経由せず個人でも AWS Educate に参加することも可能である. AWS Educate からは様々な学習教材が提供されているので,ぜひ活用してもらいたい.

    環境構築

    本書では, AWS 上にクラウドアプリケーションを展開するハンズオンを実施する. そこで紹介するプログラムを実行するためには,以下の計算機環境が必要である. インストールの方法については,巻末付録 ( (#sec:appendix_settingup)) に記してある. 必要に応じて参照し,環境構築を各自実施していただきたい.

    • UNIX 系コンソール: ハンズオンで紹介するコマンドを実行したり, SSH でサーバーにアクセスするため, UNIX 系のコンソール環境が必要である. Mac または Linux のユーザーは, OS に標準搭載のコンソール(ターミナルとも呼ばれる)を使用すればよい. Windows のユーザーは, Windows Subsystem for Linux (WSL) を使い, Linux の仮想環境のインストールを推奨する ( (#sec:install_wsl) 参照).

    • Docker: 本書では Docker とよばれる仮想計算環境の利用方法を解説する. インストール手順については (#sec:install_docker) を参照のこと.

    • Python: Version 3.6 以上をインストールする. とくに,ハンズオンでは venv モジュールを使用する. venv の使い方は (#venv_quick_guide) 参照のこと.

    • Node.js: version 12.0 以上 をインストールする.

    • AWS CLI: Version 2 をインストールする. インストール手順については (#aws_cli_install) 参照のこと.

    • AWS CDK: Version 1.100 以上をインストールする. Version 2 以降には未対応である. インストール手順については (#aws_cdk_install) 参照のこと.

    • AWS 認証鍵の設定: AWS API をコマンドラインから呼ぶには,認証鍵 (secret key) が設定されている必要がある. 認証鍵の設定については (#aws_cli_install) 参照のこと.

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は (#sec_handson_docker) に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    • Python の基本的な理解: 本書では Python を使ってプログラムの作成を行う. 使用するライブラリは十分抽象化されており,関数の名前を見ただけで意味が明瞭なものがほとんどであるので, Python に詳しくなくても心配する必要はない.

    • Linux コマンドラインの基礎的な理解: クラウドを利用する際,クラウド上に立ち上がるサーバーは基本的に Linux である. Linux のコマンドラインについて知識があると,トラブルシュートなどが容易になる. 筆者のおすすめの参考書は The Linux Command Line by William Shotts である. ウェブで無料で読むことができるので,読んだことのない人はぜひ一読を.

    講義に関連する資料

    ハンズオンで使うプログラムや教科書のソースコードは以下のウェブページで公開している.

    本書で使用するノーテーションなど

    • コードやシェルのコマンドは monospace letter で記述する.

    • シェルに入力するコマンドは,それがシェルコマンドであると明示する目的で,先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力には $ はついていない点に留意する.

    また,以下のような形式で注意やチップスを提供する.

    追加のコメントなどを記す.

    発展的な議論やアイディアなどを紹介する.

    陥りやすいミスなどの注意事項を述べる.

    絶対に犯してはならないミスを指摘する.

    + \ No newline at end of file diff --git a/development/aws/license.html b/development/aws/license.html index 3fd2b202..1baed3e4 100644 --- a/development/aws/license.html +++ b/development/aws/license.html @@ -5,15 +5,15 @@ ライセンス | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
    Skip to content

    ライセンス

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:62
    Reading:1 min

    本教科書およびハンズオンのソースコードは CC BY-NC-ND 4.0 に従うライセンスで公開しています.

    教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.

    cc_by_nc_nd

    - +
    Skip to content

    ライセンス

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:62
    Reading:1 min

    本教科書およびハンズオンのソースコードは CC BY-NC-ND 4.0 に従うライセンスで公開しています.

    教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.

    cc_by_nc_nd

    + \ No newline at end of file diff --git a/development/aws/main.html b/development/aws/main.html index 2450b74c..49af3e00 100644 --- a/development/aws/main.html +++ b/development/aws/main.html @@ -5,12 +5,12 @@ はじめに! | Toshiki's Note - + - + - + @@ -28,7 +28,7 @@ - + @@ -51,1924 +51,1924 @@ -
    Skip to content

    はじめに!

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:34.3k
    Reading:141 min

    本書の目的・内容

    本書は,東京大学計数工学科で 2021 年度 S1/S2 タームに開講されている"システム情報工学特論"の講義資料として作成された.

    本書の目的は,クラウドの初心者を対象とし,クラウドの基礎的な知識・概念を解説する. また, Amazon Web Services (以下, AWS) の提供するクラウド環境を実例として,具体的なクラウドの利用方法をハンズオンを通して学ぶ.

    とくに,科学・エンジニアリングの学生を対象として,研究などの目的でクラウドを利用するための実践的な手順を紹介する. 知識・理論の説明は最小限に留め,実践を行う中で必要な概念の解説を行う予定である. 読者が今後,研究などでクラウドを利用する際の,足がかりとなれば本書の目的は十分達成されたことになる.

    本書は以下のような三部構成になっている.

    本書の構成
    テーマハンズオン

    第一部 (1章-4章)

    クラウドの基礎

    • AWSに自分のサーバーを立ち上げる

    第二部 (5章-9章)

    クラウドを活用した機械学習

    • AWS と Jupyter を使って始めるディープラーニング

    • スケーラブルな自動質問回答ボットを作る

    • 並列化されたハイパーパラメータサーチの実装

    第三部 (10章-13章)

    サーバーレスアーキテクチャ入門

    • Lambda, DynamoDB, S3 の演習

    • 俳句を投稿する SNS "Bashoutter" を作る

    第一部は,クラウドの基礎となる概念・知識を解説する. セキュリティやネットワークなど,クラウドを利用する上で最低限おさえなければいけないポイントを説明する. ハンズオンでは,はじめての仮想サーバーを AWS に立ち上げる演習を行う.

    第二部では,クラウド上で科学計算 (とくに機械学習) を走らせるための入門となる知識・技術を解説する. あわせて, Docker とよばれる仮想計算環境の使用方法を紹介する. 一つ目のハンズオンでは, AWS のクラウドで Jupyter Notebook を起動し簡単な機械学習の計算を走らせる課題を実践する. 二つ目のハンズオンでは,深層学習を用いた自然言語処理により,質問に自動で回答を生成するボットを作成する. 最後に,複数台の GPU インスタンスからなるクラスターを起動し,並列に深層学習のハイパーパラメータサーチを行う方法を紹介する.

    第三部では,サーバーレスアーキテクチャとよばれる最新のクラウドのアーキテクチャを紹介する. これは,サーバーの処理能力を負荷に応じてより柔軟に拡大・縮小するための概念であり,それ以前 (Serverful としばしばよばれる) と質的に異なる設計思想をクラウドに導入するものである. ハンズオンでは,サーバーレスクラウドの主要なコンポーネントである Lambda, DynamoDB, S3 の演習を提供する. さらに,サーバーレスの技術を使用して簡単な SNS をクラウド上に作成する.

    これらの豊富なハンズオンにより, AWS 上にクラウドシステムを開発するための知識と技術が身につくはずである. いずれのハンズオンも,実用性を重視したものになっており,これらをベースにカスタマイズを施すことで様々な応用が可能である.

    本書のフィロソフィー

    本書のフィロソフィーを一言で表すなら, "ロケットで宇宙まで飛んでいって一度地球を眺めてみよう!" である.

    どういうことか?

    ここでいう"地球"とは,クラウドコンピューティングの全体像のことである. 言うまでもなく,クラウドという技術は非常に広範かつ複雑な概念で,幾多の情報技術・ハードウェア・アルゴリズムが精緻に組み合わさってできた総体である. そして,今日では科学研究から日常のインフラ設備に至るまで,我々の社会の多くの部分がクラウド技術によって支えられている.

    ここでいう"ロケット"とはこの講義のことである. この講義では,ロケットに乗って宇宙まで飛び立ち,地球(クラウド)の全体を自身の目で眺めてもらう. その際,ロケットの成り立ちや仕組み (背後にある要素技術やプログラムのソースコード) を深くは問わない. 将来,自分が研究などの目的でクラウドを利用することになった際に,改めて学んでもらえば良い. 本書の目的はむしろ,クラウドの最先端に実際に触れ,そこからどんな景色が見えるか(どんな応用が可能か)を実感してもらうことである.

    そのような理由で,本書はクラウドの基礎から応用まで幅広いテーマを取り扱う. 第一部はクラウドの基礎から始め,第二部では一気にレベルアップし機械学習(深層学習)をクラウドで実行する手法を解説する. さらに第三部では,サーバーレス・アーキテクチャというここ数年のうちに確立した全く新しいクラウドの設計について解説する. それぞれで本一冊分以上の内容に相当するものであるが,本書はあえてこれらを一冊にまとめ連続的に俯瞰するという野心的な意図をもって執筆された.

    決して楽な搭乗体験ではないかもしれないが,このロケットにしがみついてきてもらえれば,とてもエキサイティングな景色が見られることを約束したい.

    宇宙からみた地球 (Image from NASA https://www.nasa.gov/image-feature/planet-of-clouds)

    AWS アカウント

    本書では,ハンズオン形式で AWS のクラウドを実際に動かす演習を提供する. 自分でハンズオンを実行してみたい読者は,各自で AWS のアカウントの作成をしていただく. AWS のアカウントの作成の仕方は巻末付録 (AWS アカウントの取得) に簡単に記載したので,必要に応じて参照していただきたい.

    AWS にはいくつかの機能に対して無料利用枠が設定されており,いくつかのハンズオンは無料の範囲内で実行できる. 一方,ほかのハンズオン (とくに機械学習を扱うもの) では数ドル程度のコストが発生する. ハンズオンごとに発生するおおよそのコストについて記述があるので,注意をしながらハンズオンに取り組んでいただきたい.

    また,大学などの教育機関における講義で AWS を使用する際は, AWS Educate というプログラムを利用することも可能である. これは,講義の担当者が申請を行うことで,受講する学生に対し AWS クレジットが提供されるというプログラムである. AWS Educate を利用することで金銭的な負担なしに AWS を体験することができる. また,講義を経由せず個人でも AWS Educate に参加することも可能である. AWS Educate からは様々な学習教材が提供されているので,ぜひ活用してもらいたい.

    環境構築

    本書では, AWS 上にクラウドアプリケーションを展開するハンズオンを実施する. そこで紹介するプログラムを実行するためには,以下の計算機環境が必要である. インストールの方法については,巻末付録 (Appendix: 環境構築) に記してある. 必要に応じて参照し,環境構築を各自実施していただきたい.

    • UNIX 系コンソール: ハンズオンで紹介するコマンドを実行したり, SSH でサーバーにアクセスするため, UNIX 系のコンソール環境が必要である. Mac または Linux のユーザーは, OS に標準搭載のコンソール(ターミナルとも呼ばれる)を使用すればよい. Windows のユーザーは, Windows Subsystem for Linux (WSL) を使い, Linux の仮想環境のインストールを推奨する (WSL のインストール 参照).

    • Docker: 本書では Docker とよばれる仮想計算環境の利用方法を解説する. インストール手順については Docker のインストール を参照のこと.

    • Python: Version 3.6 以上をインストールする. とくに,ハンズオンでは venv モジュールを使用する. venv の使い方は Python クイックガイド 参照のこと.

    • Node.js: version 12.0 以上 をインストールする.

    • AWS CLI: Version 2 をインストールする. インストール手順については AWS CLI のインストール 参照のこと.

    • AWS CDK: Version 1.100 以上をインストールする. Version 2 以降には未対応である. インストール手順については AWS CDK のインストール 参照のこと.

    • AWS 認証鍵の設定: AWS API をコマンドラインから呼ぶには,認証鍵 (secret key) が設定されている必要がある. 認証鍵の設定については AWS CLI のインストール 参照のこと.

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は ハンズオン実行用の Docker image の使い方 に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    • Python の基本的な理解: 本書では Python を使ってプログラムの作成を行う. 使用するライブラリは十分抽象化されており,関数の名前を見ただけで意味が明瞭なものがほとんどであるので, Python に詳しくなくても心配する必要はない.

    • Linux コマンドラインの基礎的な理解: クラウドを利用する際,クラウド上に立ち上がるサーバーは基本的に Linux である. Linux のコマンドラインについて知識があると,トラブルシュートなどが容易になる. 筆者のおすすめの参考書は The Linux Command Line by William Shotts である. ウェブで無料で読むことができるので,読んだことのない人はぜひ一読を.

    講義に関連する資料

    ハンズオンで使うプログラムや教科書のソースコードは以下のウェブページで公開している.

    https://github.com/tomomano/learn-aws-by-coding

    本書で使用するノーテーションなど

    • コードやシェルのコマンドは monospace letter で記述する.

    • シェルに入力するコマンドは,それがシェルコマンドであると明示する目的で,先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力には $ はついていない点に留意する.

    また,以下のような形式で注意やチップスを提供する.

    追加のコメントなどを記す.

    発展的な議論やアイディアなどを紹介する.

    陥りやすいミスなどの注意事項を述べる.

    絶対に犯してはならないミスを指摘する.

    クラウド概論

    クラウドとは?

    Cloud

    クラウドとはなにか? クラウドという言葉は,それ自身がとても広い意味をもつので,厳密な定義付けを行うことは難しい.

    学術的な意味でのクラウドの定義づけをするとしたら,NIST(米国・国立標準技術研究所) による The NIST Definition of Cloud Computing が引用されることが多い. ここに記載されたクラウドの定義・モデルを図示したのが figure_title である.

    The NIST Definition of Cloud Computing

    これによると,クラウドとは以下の要件が満たされたハードウェア/ソフトウェアの総体のことをいう.

    • On-demand self-service 利用者のリクエストに応じて計算資源が自動的に割り当てられる.

    • Broad network access 利用者はネットワークを通じてクラウドにアクセスできる.

    • Resource pooling クラウドプロバイダーは,所有する計算資源を分割することで複数の利用者に計算資源を割り当てる.

    • Rapid elasticity 利用者のリクエストに応じて,迅速に計算資源の拡大あるいは縮小を行うことができる.

    • Measured service 計算資源の利用量を計測・監視することができる.

    …と,いわれても抽象的でよくわからないかもしれない.もう少し具体的な話をする.

    個人が所有する計算機で, CPU をアップグレードしようと思ったら,物理的に筐体を開け,CPU ソケットを露出させ,新しい CPU に交換する必要があるだろう. あるいは,ストレージがいっぱいになってしまったら,古いディスクを抜き取り,新しいディスクを挿入する必要がある. 計算機の場所を移動させたときには,新しい部屋の LAN ケーブルを差し込まないとネットワークには接続できない.

    クラウドでは,これらの操作がプログラムからのコマンドによって実行できる. CPU が 1000 個欲しいと思ったならば,そのようにクラウドプロバイダーにリクエストを送れば良い. すると,数分もしないうちに 1000 CPU の計算資源が割り当てられる. ストレージを 1TB から 10TB に拡張しようと思ったならば,そのようにコマンドを送ればよい (これは,Google Drive や Dropbox などのサービスなどで馴染みのある人も多いだろう). 計算資源を使い終わったら,そのことをプロバイダーに伝えれば,割り当て分はすぐさま削除される. クラウドプロバイダーは,使った計算資源の量を正確にモニタリングしており,その量をもとに利用料金の計算が行われる.

    このように,クラウドの本質は物理的なハードウェアの仮想化・抽象化であり,利用者はコマンドを通じて,まるでソフトウェアの一部かのように,物理的なハードウェアの管理・運用を行うことができる. もちろん,背後では,データセンターに置かれた膨大な数の計算機が大量の電力を消費しながら稼働している. クラウドプロバイダーはデータセンターの計算資源を上手にやりくりし,ソフトウェアとしてのインターフェースをユーザーに提供することで,このような仮想化・抽象化を達成しているわけである. クラウドプロバイダーの視点からすると,大勢のユーザーに計算機を貸し出し,データセンターの稼働率を常時 100%に近づけることで,利益率の最大化を図っているのである.

    著者の言葉で,クラウドの重要な特性を定義するならば,以下のようになる.

    クラウドとは計算機ハードウェアの抽象化である.つまり,物理的なハードウェアをソフトウェアの一部かのように自在に操作・拡大・接続することを可能にする技術である.

    先述の The NIST Definition of Cloud Computing に戻ると,クラウドプロバイダーによるクラウドサービスの形態としては,次の三つが定義されている (figure_title).

    • Software as a Service (SaaS): クラウド上で実行されるアプリケーションをサービスとして利用者に提供する形態. 例として, Google Drive や Slack などが挙げられる. 利用者は,背後にあるクラウドのインフラ (ネットワークやサーバーなど) には直接触れず,アプリケーションとして提供されているクラウドサービスを享受する.

    • Platform as a Service (PaaS): 顧客の作成したアプリケーション (多くの場合データベースと API リクエスト処理を行うサーバーのコードから構成される) をデプロイする環境をサービスとして利用者に提供する形態. PaaS では利用者はクラウドのインフラに直接触れることはなく,計算負荷が増減した際のサーバーのスケーリングはクラウドプロバイダーによってなされる. 例としては, Google App Engine や Heroku などがある.

    • Infrastructure as a Service (IaaS): クラウド上の計算インフラストラクチャーを従量課金制で利用者に提供する形態. 利用者は必要なネットワーク・サーバー・ストレージをプロバイダーから借り受け,そこに自身のアプリケーションを展開し運用する. IaaS の例としては AWS EC2 などが挙げられる.

    本書が扱うのは,主に IaaS におけるクラウド開発である. すなわち,開発者がクラウドのインフラを直接操作し,所望のネットワーク・サーバー・ストレージなどを一から構成し,そこにアプリケーションを展開するというクラウド開発である. この意味において,クラウドの開発とはクラウドインフラストラクチャーを定義・展開するプログラムを構築するステップインフラ上で実際に走るアプリケーションを作成するステップの二つに分けることができる. この二つは,プログラマーの技術としてはある程度分業を行うことが可能であるが,最も効率化・最適化されたクラウドシステムを構築するためには両方の理解が必須である. 本書では,前者 (クラウドインフラの記述) に重きを置きつつ,アプリケーションレイヤーの話題も取り扱う. PaaS とは,開発者はアプリケーションレイヤーの開発に注力し,クラウドインフラの部分はクラウドプロバイダーに依存するという概念である. PaaS は,クラウドインフラの開発が不要になることで開発の時間が短縮されるが,細かなインフラの挙動はコントロールできないという限界がある. 本書では PaaS についてはとくに取り扱わない.

    SaaS は本書の文脈では開発による"成果物"と捉えられるだろう. すなわち, IaaS を構成するプログラムを作成し展開することによって,一般の人が利用できるようなウェブ上の計算サービスやデータベースを提供することが開発の最終ゴールである. 本書のハンズオンではその実例として,シンプルな SNS の作成 (Hands-on #6: Bashoutter) などの演習を提供する.

    なお,最近では Function as a Service (FaaS) やサーバーレスコンピューティングなども新たなクラウドのカテゴリとして認知されている. これらの概念については Hands-on #5: サーバーレス入門 などの章で詳しく触れていく. 本書を読み進める中で明らかになるように,クラウドの技術は日進月歩である. 本書では実用的・教育的な観点から,従来的なクラウドの設計概念に触れたあと,サーバーレスなどの最新の技術も網羅するので,楽しみにしながら読み進めていただきたい.

    最後に,The NIST Definition of Cloud Computing によると,クラウドの運用形態について次のような定義がなされている (figure_title). 特定の組織・団体・企業の内部のみで使用されるクラウドを,プライベートクラウド (private cloud) とよぶ. 例えば,大学や研究機関では,その機関の構成員向けの大規模計算機サーバーが運用されていることが多い. プライベートクラウドは,組織の構成員ならば無料もしくは極めて割安のコストで計算を実行できる. しかし,使用できる計算資源の上限は限られる場合が多く,拡張時の柔軟性に欠ける場合もある.

    一方,商用のサービスとして一般の顧客に向けたクラウドのことを,パブリッククラウド (public cloud) とよぶ. 有名なパブリッククラウドプラットフォームの例を挙げると, Google 社が提供する Google Cloud Platform (GCP), Microsoft 社が提供する Azure, Amazon 社が提供する Amazon Web Services (AWS) などがある. パブリッククラウドを利用する場合は,プロバイダーの設定した利用料金を支払うことになる. その分,巨大なデータセンターを運用する企業の計算資源にアクセスすることができるので,計算のキャパシティは無尽蔵にあるといって過言でない.

    第三のクラウドの運用形態として,コミュニティクラウド (community cloud) が挙げられる. これは,例えば政府の省庁・機関など目的・役割を共有する団体・組織が共有して運用するクラウドを指す. 最後に,ハイブリッドクラウド (hybrid cloud) という形態もあり,これはプライベート・パブリック・コミュニティクラウドの二つ以上の組み合わせによって構成されるクラウドのことである. データ保護の観点から,いくつかの機密データやプライバシーに関わる情報はプライベートクラウドに保持し,残りのシステムをパブリッククラウドに依存する,などの形態が想定される.

    本書で説明するのは,基本的にパブリッククラウドを使ったクラウド開発である. 特に,Amazon Web Services (AWS) を使用して,具体的な技術と概念を学んでいく. 一方で,サーバーのスケーリングや仮想計算環境などのテクニックはすべてのクラウドに共通な概念であるので,クラウドのプラットフォームが変わろうと一般に通用する知識も同時に身につくはずだ.

    なぜクラウドを使うのか?

    上述のように,クラウドとはプログラムを通じて自由に計算資源を操作することのできる計算環境である. ここでは,リアルなローカル計算環境と比べて,なぜクラウドを使うと良いことがあるのかについて述べたい.

    1. 自由にサーバーのサイズをスケールできる

      なにか新しいプロジェクトを始めるとき,あらかじめ必要なサーバーのスペックを知るのは難しい. いきなり大きなサーバーを買うのはリスクが高い. 一方で,小さすぎるサーバーでは,後のアップグレードが面倒である. クラウドを利用すれば,プロジェクトを進めながら,必要な分だけの計算資源を確保することができる. 2. 自分でサーバーをメンテナンスする必要がない

      悲しいことに,コンピュータとは古くなるものである.最近の技術の進歩の速度からすると,5 年も経てば,もはや当時の最新コンピュータも化石と同じである. 5 年ごとにサーバーを入れ替えるのは相当な手間である. またサーバーの停電や故障など不意の障害への対応も必要である. クラウドでは,そのようなインフラの整備やメンテナンスはプロバイダーが自動でやってくれるので,ユーザーが心配する必要がない. 3. 初期コスト 0

      自前の計算環境とクラウドの,経済的なコストのイメージを示したのが figure_title である. クラウドを利用する場合の初期コストは基本的に 0 である. その後,使った利用量に応じてコストが増大していく. 一方,自前の計算環境では,大きな初期コストが生じる. その分,初期投資後のコストの増加は,電気利用料やサーバー維持費などに留まるため,クラウドを利用した場合よりも傾きは小さくなる. 自前の計算機では,ある一定期間後,サーバーのアップグレードなどによる支出が生じることがある. 一方,クラウドを利用する場合は,そのような非連続なコストの増大は基本的に生じない. クラウドのコストのカーブが,自前計算環境のコストのカーブの下にある範囲においては,クラウドを使うことは経済的なコスト削減につながる.

      クラウドと自前計算機環境の経済的コストの比較

    とくに,**1.**の点は研究の場面では重要であると筆者は感じる. 研究をやっていて,四六時中計算を走らせ続けるという場合は少ない. むしろ,新しいアルゴリズムが完成したとき・新しいデータが届いたとき,集中的・突発的に計算タスクが増大することが多いだろう. そういったときに,フレキシブルに計算力を増強させることができるのは,クラウドを使う大きなメリットである.

    ここまでクラウドを使うメリットを述べたが,逆に,デメリットというのも当然存在する.

    1. クラウドは賢く使わないといけない

      figure_title で示したコストのカーブにあるとおり,使い方によっては自前の計算環境のほうがコスト的に有利な場面は存在しうる. クラウドを利用する際は,使い終わった計算資源はすぐに削除するなど,利用者が賢く管理を行う必要があり,これを怠ると思いもしない額の請求が届く可能性がある. 2. セキュリティ

      クラウドは,インターネットを通じて世界のどこからでもアクセスできる状態にあり,セキュリティ管理を怠ると簡単にハッキングの対象となりうる. ハッキングを受けると,情報流出だけでなく,経済的な損失を被る可能性がある. 3. ラーニングカーブ

      上記のように,コスト・セキュリティなど,クラウドを利用する際に留意しなければならない点は多い. 賢くクラウドを使うには,十分なクラウドの理解が必要であり,そのラーニングカーブを乗り越える必要がある.

    Mac/Linux などでコマンドを入力するときに使用する,あの黒い画面のことを Terminal とよんだりする. この言葉の語源をご存知だろうか?

    Terminal

    この言葉の語源は,コンピュータが誕生して間もない頃の時代に遡る. その頃のコンピュータというと,何千何万のという数の真空管が接続された,会議室一個分くらいのサイズのマシンであった. そのような高価でメンテが大変な機材であるから,当然みんなでシェアして使うことが前提となる. ユーザーがコンピュータにアクセスするため,マシンからは何本かのケーブルが伸び,それぞれにキーボードとスクリーンが接続されていた… これを Terminal とよんでいたのである. 人々は,代わる代わる Terminal の前に座って,計算機との対話を行っていた.

    時代は流れ,Windows や Mac などのいわゆるパーソナルコンピュータの出現により,コンピュータはみんなで共有するものではなく,個人が所有するものになった.

    最近のクラウドの台頭は,みんなで大きなコンピュータをシェアするという,最初のコンピュータの使われ方に原点回帰していると捉えることもできる. 一方で,スマートフォンやウェアラブルなどのエッジデバイスの普及も盛んであり,個人が複数の"小さな"コンピュータを所有する,という流れも同時に進行しているのである.

    AWS 入門

    AWS とは?

    本書では,クラウドの実践を行うプラットフォームとして, AWS を用いる. 実践にあたって,最低限必要な AWS の知識を本章では解説しよう.

    AWS (Amazon Web Services) は Amazon 社が提供する総合的なクラウドプラットフォームである. AWS は Amazon 社が持つ膨大な計算リソースを貸し出すクラウドサービスとして,2006 年に誕生した. 2021 年では,クラウドプロバイダーとして最大のマーケットシェア (約 32%) を保持している (参照). Netflix や Slack をはじめとした多くのウェブ関連のサービスで,一部または全てのサーバーリソースが AWS から提供されているとのことである. よって,知らないうちに AWS の恩恵にあずかっている人も少なくないはずだ.

    最大のシェアをもつだけに,機能・サービスの幅広さはほかのクラウドプラットフォームと比べ抜きんでている. また,利用者数が多いことを反映して,公式あるいはサードパーティによる技術紹介記事が数多くウェブ上に存在しているだけでなく,ライブラリのユーザーコミュニティも大きく問題解決が捗るのも魅力の一つだ. 初期のころウェブビジネスを行う企業がユーザーの大半を占めていたが,最近は大学などでの科学研究用途としても頻繁に用いられるようになってきている.

    AWS の機能・サービス

    figure_title は,執筆時点において AWS で提供されている主要な機能・サービスの一覧である.

    AWSで提供されている主要なサービス一覧

    計算,ストレージ,データベース,ネットワーク,セキュリティなど,クラウドの構築に必要な様々な要素が独立したコンポーネントとして提供されている. 基本的に,これらを組み合わせることで一つのクラウドシステムができあがる.

    また,機械学習・音声認識・AR/VR など,特定のアプリケーションにパッケージ済みのサービスも提供されている. これらを合計すると全部で 170 個以上のサービスが提供されているとのことである (参照).

    AWS の初心者が陥りがちなのは,大量のサービスの数に圧倒され,どこから手をつけたらよいのかわからなくなる,という状況である. たくさんのサービスの中から,どのサービスをどの順番で学んでいったらいいのか,その道筋すら明らかでなく,大きな参入障壁となっていることは間違いない. だが実のところ, AWS の基本的な構成要素はそのうちの数個のみに限られる. 基本要素となる機能の使い方を知れば, AWS のおおよそのリソースを使いこなすことが可能になる. ほかの機能の多くは,基本の要素を組み合わせて特定のアプリケーションに特化したパッケージとして AWS が用意したものである. そのポイントを認知することが, AWS の学習の最初のステップである.

    ここでは, AWS 上でクラウドシステムを構築するときの基本となる構成要素を列挙する. これらは後のハンズオンで実際にプログラムを書きながら体験する. 現時点では,名前だけでも頭の片隅に記憶してもらえればよい.

    計算

    S3 EC2 (Elastic Compute Cloud) 様々なスペックの仮想マシンを作成し,計算を実行することができる. クラウドの最も基本となる構成要素である. Hands-on #1: 初めての EC2 インスタンスを起動する, Hands-on #2: AWS でディープラーニングを実践, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で詳しく触れる.

    S3 Lambda Function as a Service (FaaS) とよばれる,小さな計算をサーバーなしで実行するためのサービス. サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    ストレージ

    S3 EBS (Elastic Block Store) EC2 に付与することのできる仮想データドライブ. いわゆる"普通の"(一般的な OS で使われている)ファイルシステムを思い浮かべてくれたらよい.

    S3 S3 (Simple Storage Service) Object Storage とよばれる,API を使ってデータの読み書きを行う,いうなれば”クラウド・ネイティブ”なデータの格納システムである. サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    データベース

    S3 DynamoDB NoSQL 型のデータベースサービス (知っている人は mongoDB などを思い浮かべたらよい). サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    ネットワーク

    S3 VPC(Virtual Private Cloud) AWS 上に仮想ネットワーク環境を作成し,仮想サーバー間の接続を定義したり,外部からのアクセスなどを管理する. EC2 は VPC の内部に配置されなければならない.

    API Gateway S3 API のエンドポイントとバックエンドのサービス (Lambda など) を接続する際に用いる,リバースプロキシとしての役割を担う. Hands-on #6: Bashoutter で詳しく解説する.

    Region と Availability Zone

    AWS を使用する際に知っておかなければならない重要な概念として, リージョン (Region)Availability Zone (AZ) がある (figure_title). 以下ではこの概念について簡単に記述する.

    AWSにおける Region と Availability Zones

    リージョン (Region) とは,おおまかに言うとデータセンターの所在地のことである. 執筆時点において, AWS は世界の 25 の国と地域でデータセンターを所有している. figure_title は執筆時点で利用できるリージョンの世界地図を示している. 日本では東京と大阪にデータセンターがある. 各リージョンには固有の ID がついており,例えば東京は ap-northeast-1, 米国オハイオ州は us-east-2,などと定義されている.

    Regions in AWS(出典: https://aws.amazon.com/about-aws/global-infrastructure/)

    AWS コンソールにログインすると,画面右上のメニューバーでリージョンを選択することができる(figure_title, 赤丸で囲った箇所). EC2, S3 などの AWS のリソースは,リージョンごとに完全に独立である. したがって,リソースを新たにデプロイする際,あるいはデプロイ済みのリソースを閲覧する際は,コンソールのリージョンが正しく設定されているか,確認する必要がある. ウェブビジネスを展開する場合などは,世界の各地にクラウドを展開する必要があるが,個人的な研究用途として用いる場合は,最寄りのリージョン (i.e. 東京) を使えば基本的に問題ない.

    AWSコンソールでリージョンを選択

    Avaialibity Zone (AZ) とは,リージョン内で地理的に隔離されたデータセンターのことである. それぞれのリージョンは 2 個以上の AZ を有しており,もし一つの AZ で火災や停電などが起きた場合でも,ほかの AZ がその障害をカバーすることができる. また, AZ 間は高速な AWS 専用ネットワーク回線で結ばれているため, AZ 間のデータ転送は極めて早い. AZ は,ビジネスなどでサーバーダウンが許容されない場合などに注意すべき概念であり,個人的な用途で使う限りにおいてはあまり深く考慮する必要はない.言葉の意味だけ知っておけば十分である.

    AWS を使用する際,どこのリージョンを指定するのがよいのだろうか? インターネットの接続速度の観点からは,地理的に一番近いリージョンを使用するのが一般的によいだろう. 一方, EC2 の利用料などはリージョンごとに価格設定が若干 (10-20%程度) 異なる. したがって,自分が最も頻繁に利用するサービスの価格が最も安く設定されているリージョンを選択する,というのも重要な視点である. また,いくつかのサービスは,特定のリージョンで利用できない場合もある. これらのポイントから総合的に判断して使用するリージョンを決めると良い.

    AWS Educate を利用している読者へ

    執筆時点において,AWS Educate による Starter Account を使用している場合は us-east-1 region のみ利用できる (参照).

    AWS でのクラウド開発

    AWS のクラウドの全体像がわかってきたところで,次のトピックとして,どのようにして AWS 上にクラウドの開発を行い,展開していくかについての概略を解説しよう.

    AWS のリソースを追加・編集・削除するなどの操作を実行するには,コンソールを用いる方法と,API を用いる方法の,二つの経路がある.

    コンソール画面からリソースを操作する

    AWS のアカウントにログインすると,まず最初に表示されるのがAWS コンソールである (figure_title).

    AWSマネージメントコンソール画面

    コンソールを使うことで, EC2 のインスタンスを立ち上げたり,S3 のデータを追加・削除したり,ログを閲覧したりなど,AWS 上のあらゆるリソースの操作を GUI (Graphical User Interface) を通して実行することができる. 初めて触る機能をポチポチと試したり,デバッグを行うときなどにとても便利である

    コンソールはさらっと機能を試したり,開発中のクラウドのデバッグをするときには便利なのであるが,実際にクラウドの開発をする場面でこれを直接いじることはあまりない. むしろ,次に紹介する API を使用して,プログラムとしてクラウドのリソースを記述することで開発を行うのが一般的である. そのような理由で,本書では AWS コンソールを使った AWS の使い方はあまり触れない. AWS のドキュメンテーションには,たくさんの チュートリアル が用意されており,コンソール画面から様々な操作を行う方法が記述されているので,興味がある読者はそちらを参照されたい.

    API からリソースを操作する

    API (Application Programming Interface) を使うことで,コマンドを AWS に送信し,クラウドのリソースの操作をすることができる. API とは,端的に言えば AWS が公開しているコマンドの一覧であり,GET, POST, DELETE などの REST API から構成されている (REST API については REST API で簡単に解説する). が,直接 REST API を入力するのは面倒であるので,その手間を解消するための様々なツールが提供されている.

    例えば, AWS CLI は, UNIX コンソールから AWS API を実行するための CLI (Command Line Interface) である. CLI に加えて,いろいろなプログラミング言語での SDK (Software Development Kit) が提供されている.以下に一例を挙げる.

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    python
    import boto3
    -
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    -
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン (Hands-on #1: 初めての EC2 インスタンスを起動する) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    python
    import boto3
    -
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    import boto3
    -
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    AWS CLI のインストールについては, AWS CLI のインストール を参照.

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは AWS CLI のインストール を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    sh
    $ aws s3 ls
    -
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    -
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    sh
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
    -
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
    -
    -2020-06-07 23:54:19   13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    AWS 上のあらゆるリソースには, Amazon Resource Name (ARN) という固有の ID が付与されている. ARN は arn:aws:s3:::my_bucket/ のようなフォーマットで記述され,ARN を使用することで,特定の AWS リソース (S3 のバケットや EC2 のインスタンス) を一意的に参照することができる.

    S3 バケットや EC2 インスタンスなどには ARN に加えて,人間が読みやすい名前を定義することも可能である. この場合は,ARN または名前のどちらを用いても同じリソースを参照することが可能である.

    CloudFormation と AWS CDK

    CloudFormation による Infrastructure as Code (IaC)

    前節で述べたように,AWS API を使うことでクラウドのあらゆるリソースの作成・管理が可能である. よって,原理上は, API のコマンドを組み合わせていくことで,自分の作りたいクラウドを設計することができる.

    しかし,ここで実用上考慮しなければならない点が一つある. AWS API には大きく分けて,リソースを操作するコマンドと,タスクを実行するコマンドがあることである (figure_title).

    AWS APIはリソースを操作するコマンドとタスクを実行するコマンドに大きく分けられる.リソースを記述・管理するのに使われるのが, CloudFormation と CDK である.

    リソースを操作するとは,EC2 のインスタンスを起動したり,S3 のバケットを作成したり,データベースに新たなテーブルを追加する,などの静的なリソースを準備する 操作を指す. "ハコ"を作る操作とよんでも良いだろう. このようなコマンドは,クラウドのデプロイ時にのみ,一度だけ実行されればよい

    タスクを実行するコマンド とは, EC2 のインスタンスにジョブを投入したり, S3 のバケットにデータを読み書きするなどの操作を指す. これは, EC2 や S3 などのリソース ("ハコ") を前提として,その内部で実行されるべき計算を記述するものである. 前者に比べてこちらは動的な操作を担当する,と捉えることもできる.

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    json
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    -
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    -
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    -
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    -
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    python
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    -
    -class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    -
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    -
    -class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    -
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

    • AWS CDK Examples: CDK を使ったプロジェクトの例が多数紹介されている. ここにある例をテンプレートに自分のアプリケーションの開発を進めるとよい.

    Hands-on #1: 初めての EC2 インスタンスを起動する

    ハンズオンの第一回では, CDK を使って EC2 のインスタンス(仮想サーバー)を作成し,SSH でサーバーにログインする,という演習を行う. このハンズオンを終えれば,あなたは自分だけのサーバーを AWS 上に立ち上げ,自由に計算を走らせることができるようになるのである!

    準備

    ハンズオンのソースコードは GitHub の handson/ec2-get-started に置いてある.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行することができる.

    まずは,ハンズオンを実行するための環境を整える. これらの環境整備は,後のハンズオンでも前提となるものなので確実にミスなく行っていただきたい.

    • AWS Account: ハンズオンを実行するには個人の AWS アカウントが必要である. AWS アカウントの取得については AWS アカウントの取得 を参照のこと.
    • Python と Node.js: 本ハンズオンを実行するには,Python (3.6 以上),Node.js (12.0 以上) がインストールされていなければならない.
    • AWS CLI: AWS CLI のインストールについては, AWS CLI のインストール を参照. ここに記載されている認証鍵の設定も済ませておくこと.
    • AWS CDK: AWS CDK のインストールについては, AWS CDK のインストール を参照.
    • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    使用方法については ハンズオン実行用の Docker image の使い方 を参照のこと.

    SSH

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する (環境構築 を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    python
    class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class MyFirstEc2(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    • まず最初に,VPC を定義する.

    • 次に, security group (SG) を定義している. ここでは,任意の IPv4 のアドレスからの,ポート 22 (SSH の接続に使用される)への接続を許可している. それ以外の接続は拒絶される.

    • 最後に,上記で作った VPC と SG が付与された EC2 インスタンスを作成している. インスタンスタイプは t2.micro を選択し, Amazon Linux を OS として設定している.

    それぞれについて,もう少し詳しく説明しよう.

    VPC (Virtual Private Cloud)

    VPC のアイコン.

    VPC

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    python
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

    • cidr="10.10.0.0/23" : このパラメータは,VPC 内の IPv4 のレンジを指定している. CIDR 記法については, Wikipediaなどを参照. 10.10.0.0/2310.10.0.0 から 10.10.1.255 までの 512 個の連続したアドレス範囲を指している. つまり,この VPC では最大で 512 個のユニークな IPv4 アドレスが使えることになる. 今回はサーバーは一つなので 512 個は明らかに多すぎるが,VPC はアドレスの数はどれだけ作成しても無料なので,多めに作成した.

    • subnet_configuration=... : このパラメータは,VPC にどのようなサブネットを作るか,を決めている. サブネットの種類には private subnetpublic subnet の二種類がある. private subnet は基本的にインターネットとは遮断されたサブネット環境である. インターネットと繋がっていないので,セキュリティは極めて高く, VPC 内のサーバーとのみ通信を行えばよい EC2 インスタンスはここに配置する. Public subnet とはインターネットに繋がったサブネットである. 本ハンズオンで作成するサーバーは,外から SSH でログインを行いたいので, Public subnet 内に配置する. より詳細な記述は 公式ドキュメンテーション を参照.

    • natgateways=0 : これは少し高度な内容なので省略する (興味のある読者は 公式ドキュメンテーションを参照). が,これを 0 にしておかないと,NAT Gateway の利用料金が発生してしまうので,注意!

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    python
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    EC2 (Elastic Compute Cloud)

    EC2 のアイコン.

    EC2

    EC2 は AWS 上に仮想サーバーを立ち上げるサービスである. 個々の起動状態にある仮想サーバーのことをインスタンス (instance) とよぶ (しかし,口語的なコミュニケーションにおいては,サーバーとインスタンスという言葉は相互互換的に用いられることが多い).

    EC2 では用途に応じて様々なインスタンスタイプが提供されている. table_title に,代表的なインスタンスタイプの例を挙げる (執筆時点での情報). EC2 のインスタンスタイプのすべてのリストは 公式ドキュメンテーション "Amazon EC2 Instance Types" で見ることができる.

    EC2 instance types
    InstancevCPUMemory (GiB)Network bandwidth (Gbps)Price per hour ($)

    t2.micro

    1

    1

    -

    0.0116

    t2.small

    1

    2

    -

    0.023

    t2.medium

    2

    4

    -

    0.0464

    c5.24xlarge

    96

    192

    25

    4.08

    c5n.18xlarge

    72

    192

    100

    3.888

    x1e.16xlarge

    64

    1952

    10

    13.344

    table_title からわかるように, CPU は 1 コアから 96 コアまで,メモリーは 1GB から 2TB 以上まで,ネットワーク帯域は最大で 100Gbps まで,幅広く選択することができる. また,時間あたりの料金は,CPU・メモリーの占有数にほぼ比例する形で増加する. EC2 はサーバーの起動時間を秒単位で記録しており,利用料金は使用時間に比例する形で決定される. 例えば, t2.medium のインスタンスを 10 時間起動した場合,0.0464 * 10 = 0.464 ドルの料金が発生する.

    AWS には 無料利用枠 というものがあり, t2.micro であれば月に 750 時間までは無料で利用することができる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    python
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, Hands-on #2: AWS でディープラーニングを実践 でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    さて,ハンズオンのコードの理解ができたところで,プログラムを実際に実行してみよう.繰り返しになるが, 準備 での準備ができていることが前提である.

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    sh
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は Python クイックガイド に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    AWS のシークレットキーをセットする

    AWS CLI および AWS CDK を使うには, AWS のシークレットキーが設定されている必要がある. シークレットキーの発行については AWS のシークレットキーの作成 を参照のこと. シークレットキーを発行したら, AWS CLI のインストール を参照し,コマンドラインの設定を行う.

    手順をここに短く要約すると,一つ目の方法は AWS_ACCESS_KEY_ID などの環境変数を設定するやり方である. もう一つの方法は, ~/.aws/credentials に認証情報を保存しておく方式である. シークレットキーの設定は AWS CLI/CDK を使用するうえで共通のステップになるので,しっかりと理解しておくように.

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    sh
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    sh
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    おめでとう!これで,めでたく AWS 上に EC2 仮想サーバーを起動し,リモートからアクセスできるようになった!

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    sh
    $ cat /proc/cpuinfo
    -
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    $ cat /proc/cpuinfo
    -
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    sh
    $  top -n 1
    -
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    -
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    -
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    -
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    sh
    $ sudo yum update -y
    -$ sudo yum install -y python36
    $ sudo yum update -y
    -$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    sh
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    EC2 コンソール画面

    コンソール右上で,正しいリージョン (今回の場合は ap-northeast-1, Tokyo) が選択されているか,注意する!

    前章で CloudFormation について触れたが,今回デプロイしたアプリケーションも,CloudFormation のスタックとして管理されている. スタック (stack) とは, AWS リソースの集合のことを指す. 今回の場合は, VPC/EC2/SG などがスタックの中に含まれている. コンソールで CloudFormation のページに行ってみよう (figure_title).

    CloudFormation コンソール画面

    "MyFirstEc2" という名前のスタックがあることが確認できる. クリックをして中身を見てみると,EC2, VPC などのリソースがこのスタックに紐付いていることがわかる.

    スタックを削除

    これにて,第一回のハンズオンで説明すべき事柄はすべて完了した. 最後に,使わなくなったスタックを削除しよう. スタックの削除には,二つの方法がある.

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    ここまでが,本書の第一部の内容である. 盛りだくさんの内容であったが,ついてこれたであろうか?

    クラウド概論 では,クラウドの定義と用語の説明を行ったあと,なぜクラウドを使うのか,という点を議論した. 続いて AWS 入門 では,クラウドを学ぶ具体的なプラットフォームとして AWS を取り上げ, AWS を使用するにあたり最低限必要な知識と用語の説明を行った. さらに, Hands-on #1: 初めての EC2 インスタンスを起動する のハンズオンでは AWS CLI と AWS CDK を使って,自身のプライベートなサーバーを AWS 上に立ち上げる演習を行った.

    これらを通じて,いかに簡単に (たった数行のコマンドで!) 仮想サーバーを立ち上げたり,削除したりすることができるか,体験できただろう. 筆者は,クラウド概論 でクラウドの最も重要な側面はダイナミックに計算リソースを拡大・縮小できることである,と述べた. この言葉の意味が,ハンズオンを通じてより明らかになっただろうか? ここで学んだ技術を少し応用するだけで,自分のウェブページをホストする仮想サーバーを作成したり,大量のコアを搭載した EC2 インスタンスを用意して科学計算を実行するなど,いろいろなアプリケーションが実現できる.

    次章からは,今回学んだクラウドの技術を基に,より現実に即した問題を解くことを体験してもらう. お楽しみに!

    クラウドで行う科学計算・機械学習

    計算機が発達した現代では,計算機によるシミュレーションやビッグデータの解析は,科学・エンジニアリングの研究の主要な柱である. これらの大規模な計算を実行するには,クラウドは最適である. 本章から始まる第二部では,どのようにしてクラウド上で科学計算を実行するのかを,ハンズオンとともに体験してもらう. 科学計算の具体的な題材として,今回は機械学習(深層学習)を取り上げる.

    なお,本書では PyTorch ライブラリを使って深層学習のアルゴリズムを実装するが,深層学習および PyTorch の知識は不要である. 講義ではなぜ・どうやって深層学習をクラウドで実行するかに主眼を置いているので,実行するプログラムの詳細には立ち入らない. 将来,自分で深層学習を使う機会が来たときに,詳しく学んでもらいたい.

    なぜ機械学習をクラウドで行うのか?

    2010 年頃に始まった第三次 AI ブームのおかげで,学術研究だけでなく社会・ビジネスの文脈でも機械学習に高い関心が寄せられている. とくに,深層学習 (ディープラーニング) とよばれる多層のレイヤーからなるニューラルネットワークを用いたアルゴリズムは,画像認識や自然言語処理などの分野で圧倒的に高い性能を実現し,革命をもたらしている.

    深層学習の特徴は,なんといってもそのパラメータの多さである. 層が深くなるほど,層間のニューロンを結ぶ重みパラメータの数が増大していく. たとえば,最新の言語モデルである GPT-3 には1750 億個ものパラメータが含まれている. このような膨大なパラメータを有することで,深層学習は高い表現力と汎化性能を実現しているのである.

    GPT-3 に限らず,最近の SOTA (State-of-the-art) の性能を達成するニューラルネットワークでは,百万から億のオーダーのパラメータを内包することは頻繁になってきている. そのような巨大なニューラルネットを訓練 (最適化) させるのは,当然のことながら膨大な計算コストがかかる. 結果として,ひとつの計算機では丸一日以上の時間がかかる場合も珍しくない. 深層学習の発展の速度は目覚ましく,研究・ビジネス両方の観点からも,いかにスループットよくニューラルネットワークの最適化を行えるかが鍵となってくる. そのような問題を解決するのにとても有効な手段が,クラウドである! Hands-on #1: 初めての EC2 インスタンスを起動する でその片鱗を見たように,クラウドを使用することでゼロから数千に至るまでの数のインスタンスを動的に起動し,並列に計算を実行することができる. さらに,深層学習を加速させる目的で,深層学習の演算に専用設計された計算チップ (GPU など) がある. クラウドを利用すると,そのような専用計算チップも無尽蔵に利用することができる. 事実,先述した GPT-3 の学習も,詳細は明かされていないが,Microsoft 社のクラウドを使って行われたと報告されている.

    GPU による深層学習の高速化

    深層学習の計算で欠かすことのできない技術として, GPU (Graphics Processing Unit) について少し説明する.

    GPU は,その名のとおり,元々はコンピュータグラフィックスを出力するための専用計算チップである. CPU (Central Processing Unit) に対し,グラフィックスの演算に特化した設計がなされている. 身近なところでは, XBox や PS5 などのゲームコンソールなどに搭載されているし,ハイエンドなノート型・デスクトップ型計算機にも搭載されていることがある. コンピュータグラフィックスでは,スクリーンにアレイ状に並んだ数百万個の画素をビデオレート (30 fps) 以上で処理する必要がある. そのため,GPU はコアあたりの演算能力は比較的小さいかわりに,チップあたり数百から数千のコアを搭載しており (figure_title),スクリーンの画素を並列的に処理することで,リアルタイムでの描画を実現している.

    GPUのアーキテクチャ.GPUには数百から数千の独立した計算コアが搭載されている. (画像出典: https://devblogs.nvidia.com/nvidia-turing-architecture-in-depth/)

    このように,コンピュータグラフィクスの目的で生まれた GPU だが,2010 年前後から,その高い並列計算能力をグラフィックス以外の計算 (科学計算など) に用いるという流れ (General-purpose computing on GPU; GPGPU) が生まれた. GPU のコアは,その設計から,行列の計算など,単純かつ規則的な演算が得意であり,そのような演算に対しては数個程度のコアしかもたない CPU に比べて圧倒的に高い計算速度を実現することができる. 現在では GPGPU は分子動力学や気象シミュレーション,そして機械学習など多くの分野で使われている.

    ディープラーニングで最も頻繁に起こる演算が,ニューロンの出力を次の層のニューロンに伝える畳み込み (Convolution) 演算である (figure_title). 畳み込み演算は,まさに GPU が得意とする演算であり, CPU ではなく GPU を用いることで学習を飛躍的に (最大で数百倍程度) 加速させることができる.

    ニューラルネットワークにおける畳み込み演算.

    このように GPU は機械学習の計算で欠かせないものであるが,なかなか高価である. たとえば,科学計算・機械学習に専用設計された NVIDIA 社の Tesla V100 というチップは,一台で約百万円の価格が設定されている. 機械学習を始めるのに,いきなり百万円の投資はなかなか大きい. だが,クラウドを使えば,初期コスト0で GPU を使用することができる.

    機械学習を行うのに, V100 が必ずしも必要というわけではない. むしろ,研究者などでしばしば行われるのは,コンピュータゲームに使われるグラフィックス用の GPU を買ってきて (NVIDIA GeForce シリーズなど),開発のときはをそれを用いる,というアプローチである. グラフィックス用のいわゆる"コンシューマ GPU"は,市場の需要が大きいおかげで,10 万円前後の価格で購入することができる. V100 と比べると,コンシューマ GPU はコアの数が少なかったり,メモリーが小さかったりなどで劣る点があるが, それらを除いては計算能力にとくに制限があるわけではなく,開発の段階では十分な性能である場合がほとんどである. プログラムができあがって,ビッグデータの解析や,モデルをさらに大きくしたいときなどに,クラウドは有効だろう.

    クラウドで GPU を使うには, GPU が搭載された EC2 インスタンスタイプ (P3, P2, G3, G4 など) を選択しなければならない. table_title に,代表的な GPU 搭載のインスタンスタイプを挙げる (執筆時点での情報).

    GPUを搭載したEC2インスタンスタイプ
    InstanceGPUsGPU modelGPU Mem (GiB)vCPUMem (GiB)Price per hour ($)

    p3.2xlarge

    1

    NVIDIA V100

    16

    8

    61

    3.06

    p3n.16xlarge

    8

    NVIDIA V100

    128

    64

    488

    24.48

    p2.xlarge

    1

    NVIDIA K80

    12

    4

    61

    0.9

    g4dn.xlarge

    1

    NVIDIA T4

    16

    4

    16

    0.526

    table_title からわかるとおり, CPU のみのインスタンスと比べると少し高い価格設定になっている. また,古い世代の GPU (V100 に対しての K80) はより安価な価格で提供されている. 1 インスタンスあたりの GPU の搭載数は 1 台から最大で 8 台まで選択することが可能である.

    GPU を搭載した一番安いインスタンスタイプは, g4dn.xlarge であり,これには廉価かつ省エネルギー設計の NVIDIA T4 が搭載されている. 後のハンズオンでは,このインスタンスを使用して,ディープラーニングの計算を行ってみる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    V100 を一台搭載した p3.2xlarge の利用料金は一時間あたり $3.06 である. V100 が約百万円で売られていることを考えると,約 3000 時間 (= 124 日間),通算で計算を行った場合に,クラウドを使うよりも V100 を自分で買ったほうがお得になる,という計算になる (実際には,自前で V100 を用意する場合は, V100 だけでなく, CPU やネットワーク機器,電気使用料も必要なので,百万円よりもさらにコストがかかる).

    GPT-3 で使われた計算リソースの詳細は論文でも明かされていないのだが, Lambda 社のブログで興味深い考察が行われている (Lambda 社は機械学習に特化したクラウドサービスを提供している).

    記事によると,1750 億のパラメータを訓練するには,一台の GPU (NVIDIA V100) を用いた場合,342 年の月日と 460 万ドルのクラウド利用料が必要となる,とのことである. GPT-3 のチームは,複数の GPU に処理を分散することで現実的な時間のうちに訓練を完了させたのであろうが,このレベルのモデルになってくるとクラウド技術の限界を攻めないと達成できないことは確かである.

    深層学習を詳しく勉強したい人には以下の参考書を推薦したい. 深層学習の基礎的な概念や理論は普遍的であるが,この分野は日進月歩なので,常に最新の情報を取り入れることを忘れずに.

    Hands-on #2: AWS でディープラーニングを実践

    準備

    ハンズオン第二回では, GPU を搭載した EC2 インスタンスを起動し,深層学習モデルの学習と推論を実行する演習を行う.

    ハンズオンのソースコードは GitHub の handson/mnist に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. それ以外に必要な準備はない.

    初期状態の AWS アカウントでは, GPU 搭載の G タイプのインスタンスの起動上限が 0 になっていることがある. これを確認するには, AWS コンソールから EC2 の画面を開き,左のメニューから Limits を選択する. その中の Running On-Demand All G instances という数字が G インスタンスの起動上限を表している.

    もし,これが 0 になっていた場合は, AWS の自動申請フォームから上限緩和のリクエストを送る必要がある. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,東京 (ap-northeast-1) リージョンでは 0.71 $/hour のコストが発生する.

    AWS Educate Starter Account を使用している読者へ: 執筆時点においては, Starter Account には GPU 搭載型インスタンスを起動できないという制限が設けられている. したがって, Starter Account のユーザーはこのハンズオンを実行することはできない. 興味のある読者は,制限のない一般アカウントを自分自身で取得する必要があることに注意.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#2で作製するアプリケーションのアーキテクチャ

    図の多くの部分が,第一回ハンズオンで作成したアプリケーションと共通していることに気がつくだろう. 少しの変更で,簡単にディープラーニングを走らせる環境を構築することができるのである!主な変更点は次の3点である.

    • GPU を搭載した g4dn.xlarge インスタンスタイプを使用

    • ディープラーニングに使うプログラムがあらかじめインストールされた DLAMI (後述) を使用

    • SSH にポートフォワーディングのオプションつけてサーバーに接続し,サーバーで起動している Jupyter Notebook (後述) を使ってプログラムを書いたり実行したりする

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    python
    class Ec2ForDl(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class Ec2ForDl(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    -
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    -
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, クラウドで行う科学計算・機械学習 ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

    • ここでは,Deep Learning 用の諸々のソフトウェアがプリンストールされた AMI (Deep Learning Amazon Machine Image; DLAMI) を選択している (第一回では,Amazon Linux という AMI を使用していた). 使用する AMI の ID は リージョンごとに指定する必要があり,ここでは us-east-1ap-northeast-1 でそれぞれ定義している.

    DLAMI という新しい概念が出てきたので,説明しよう.

    AMI が us-east-1ap-northeast-1 でしか定義されていないので,提供されているコードはこの二つのリージョンのみでデプロイ可能である. もしほかのリージョンを利用したい場合は, AMI の ID を自身で検索し,コードに書き込む必要がある.

    DLAMI (Deep Learning Amazon Machine Image)

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    最も low-level なレイヤーとしては, GPU ドライバー がインストールされている. GPU ドライバーなしには OS は GPU とコマンドのやり取りをすることができない. 次のレイヤーが CUDAcuDNN である. CUDA は, NVIDIA 社が開発した, GPU 上で汎用コンピューティングを行うための言語であり, C++ 言語を拡張したシンタックスを備える. cuDNN は CUDA で書かれたディープラーニングのライブラリであり,n 次元の畳み込みなどの演算が実装されている. ここまでが, "Base" とよばれるタイプの DLAMI の中身である.

    これに加えて, "Conda" とよばれるタイプには, "Base" のプログラム基盤の上に, TensorFlowPyTorch などのライブラリがインストールされている. さらに, Anaconda による仮想環境を使うことによって, TensorFlow の環境・ PyTorch の環境・ MxNet の環境など,フレームワークを簡単に切り替えることができる (これについては,後のハンズオンで触れる). また, Jupyter Notebook もインストール済みである.

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    -
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    -
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    SSH ログインコマンドの <IP address> 部分は自身のインスタンスの IP アドレスを代入することを忘れずに.

    本書の提供している Docker を使ってデプロイを実行した人へ

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    Jupyter Notebook とは,インタラクティブに Python のプログラムを書いたり実行したりするためのツールである. Jupyter は GUI としてウェブブラウザを介してアクセスする形式をとっており,まるでノートを書くように,プロットやテーブルのデータも美しく表示することができる (figure_title). Python に慣れている読者は,きっと一度は使ったことがあるだろう.

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    sh
    $ cd ~ # go to home directory
    -$ jupyter notebook
    $ cd ~ # go to home directory
    -$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    Jupyter Notebook の使い方 (超簡易版)

    • Shift + Enter: セルを実行

    • Esc: Command mode に遷移

    • メニューバーの "+" ボタン または Command mode で A ⇒ セルを追加

    • メニューバーの "ハサミ" ボタン または Command mode で X ⇒ セルを削除

    ショートカットの一覧などは Ventsislav Yordanov 氏によるブログ が参考になる.

    PyTorch はじめの一歩

    PyTorch は Facebook AI Research LAB (FAIR) が中心となって開発を進めている,オープンソースのディープラーニングのライブラリである. PyTorch は 有名な例で言えば Tesla 社の自動運転プロジェクトなどで使用されており,執筆時点において最も人気の高いディープラーニングライブラリの一つである. 本ハンズオンでは, PyTorch を使ってディープラーニングの実践を行う.

    PyTorch の歴史のお話

    Facebook は PyTorch のほかに Caffe2 とよばれるディープラーニングのフレームワークを開発していた (初代 Caffe は UC Berkley の博士課程学生だった Yangqing Jia によって創られた). Caffe2 は 2018 年に PyTorch プロジェクトに合併された.

    また,2019 年 12 月,日本の Preferred Networks 社が開発していた Chainer も開発を終了し,PyTorch の開発チームと協業していくことが発表された (詳しくは プレスリリース を参照). PyTorch には,開発統合前から Chainer からインスパイアされた API がいくつもあり, Chainer の DNA は今も PyTorch に引き継がれているのである…!

    本格的なディープラーニングの計算に移る前に, PyTorch ライブラリを使って, GPU で計算を行うとはどういうものか,その入り口に触れてみよう.

    まずは,新しいノートブックを作成する. Jupyter のホーム画面の右上の "New" を押し,"conda_pytorch_p36" という環境を選択したうえで,新規ノートブックを作成する (figure_title). "conda_pytorch_p36" の仮想環境には, PyTorch がインストール済みである.

    新規ノートブックの作成. "conda_pytorch_p36" の環境を選択する.

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    python
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    python
    x = torch.rand(3,3)
    -print(x)
    x = torch.rand(3,3)
    -print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    python
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    python
    z = x + y
    -print(z)
    z = x + y
    -print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    python
    z = z.to("cpu")
    -print(z)
    z = z.to("cpu")
    -print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    完成した Jupyter Notebook は /handson/mnist/pytorch/pytorch_get_started.ipynb にある. Jupyter の画面右上の "Upload" からこのファイルをアップロードして,コードを走らせることが可能である.

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    python
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -
    -%time z = torch.matmul(x,y)
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -
    -%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    python
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    -
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    -
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    このベンチマークでは, dtype=torch.float32 と指定することで,32bit の浮動小数点型を用いている. ディープラーニングの学習および推論の計算には,32bit 型,場合によっては 16bit 型が使われるのが一般的である. これの主な理由として,教師データやミニバッチに起因するノイズが,浮動小数点の精度よりも大きいことがあげられる. 32bit/16bit を採用することで,メモリー消費を抑えたり,計算速度の向上が達成できる.

    上記のベンチマークから,GPU を用いることで,約 10 倍のスピードアップを実現することができた. スピードアップの性能は,演算の種類や行列のサイズに依存する. 行列積は,そのなかでも最も速度向上が見込まれる演算の一つである.

    実践ディープラーニング! MNIST 手書き数字認識タスク

    ここまで,AWS 上でディープラーニングの計算をするための概念や前提知識をながながと説明してきたが,ついにここからディープラーニングの計算を実際に走らせてみる.

    ここでは,機械学習のタスクで最も初歩的かつ有名な MNIST データセットを使った数字認識を扱う (figure_title). これは,0 から 9 までの手書きの数字の画像が与えられ,その数字が何の数字なのかを当てる,というシンプルなタスクである.

    MNIST 手書き数字データセット

    今回は, MNIST 文字認識タスクを,畳み込みニューラルネットワーク (Convolutional Neural Network; CNN) を使って解く. ソースコードは /handson/minist/pytorch/ にある mnist.ipynbsimple_mnist.py である. なお,このプログラムは, PyTorch の公式 Example Project 集 を参考に,多少の改変を行ったものである.

    まずは,カスタムのクラスや関数が定義された simple_mnist.py をアップロードしよう (figure_title). 画面右上の "Upload" ボタンをクリックし,ファイルを選択することでアップロードができる. この Python プログラムの中に,CNN のモデルや,学習の各イテレーションにおけるパラメータの更新などが記述されている. 今回はこの中身を説明することはしないが,興味のある読者は自身でソースコードを読んでみるとよい.

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    python
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    -
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    -
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    python
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    -
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    -
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    -
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    -
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    python
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    -
    -print("Example data size:", example_data.shape)
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    -
    -print("Example data size:", example_data.shape)
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    python
    model = Model()
    -model.to("cuda") # load to GPU
    model = Model()
    -model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    python
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    -
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    -
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    python
    model.eval()
    -
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    model.eval()
    -
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    -
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は スタックを削除 参照).

    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    Docker 入門

    ここまでの章で扱ってきたハンズオンでは,単一のサーバーを立ち上げ,それに SSH でログインをして,コマンドを叩くことで計算を行ってきた. いわば,パーソナルコンピュータの延長のような形でクラウドを使ってきたわけである. このような,インターネットのどこからでもアクセスできるパーソナルコンピュータとしてのクラウドという使い方も,もちろん便利であるし,いろいろな応用の可能性がある. しかし,これだけではクラウドの本当の価値は十分に発揮されていないと言うべきだろう. クラウド概論 で述べたように,現代的なクラウドの一番の強みは自由に計算機の規模を拡大できることにある. すなわち,多数のサーバーを同時に起動し,複数のジョブを分散並列的に実行させることで大量のデータを処理してこそ,クラウドの本領が発揮されるのである.

    本章からはじまる 3 章分 (Docker 入門, Hands-on #3: AWS で自動質問回答ボットを走らせる, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) を使って,クラウドを利用することでどのように大規模な計算システムを構築しビッグデータの解析に立ち向かうのか,その片鱗をお見せしたい. とくに,前章で扱った深層学習をどのようにビッグデータに適用していくかという点に焦点を絞って議論していきたい. そのための前準備として,本章では Docker とよばれる計算機環境の仮想化ソフトウェアを紹介する (figure_title). 現代のクラウドは Docker なしには成り立たないといっても過言ではないだろう. クラウドに限らず,ローカルで行う計算処理にも Docker は大変便利である. AWS からは少し話が離れるが,しっかりと理解して前に進んでもらいたい.

    機械学習の大規模化

    先ほどから"計算システムの大規模化"と繰り返し唱えているが,それは具体的にはどのようなものを指しているのか? ここでは大規模データを処理するための計算機システムを,機械学習を例にとって見てみよう.

    クラウドで行う科学計算・機械学習 で紹介した GPT-3 のような,超巨大な数のパラメータを有する深層学習モデルを学習させたいとしよう. そのような計算を行いたい場合,一つのサーバーでは計算力が到底足りない. したがって,典型的には figure_title に示すような計算システムの設計がなされる. すなわち,大量の教師データを小さなチャンクとして複数のマシンに分散し,並列的にニューラルネットのパラメータを最適化していくという構造である.

    複数の計算機を使った大規模な深層学習モデルの訓練

    あるいは,学習済みのモデルを大量のデータに適用し,解析を行いたいとしよう. たとえば, SNS のプラットフォームで大量の画像が与えられて,それぞれの写真に何が写っているのかをラベルづけする,などのアプリケーションを想定できる. そのような場合は, figure_title のようなアーキテクチャが考えられるだろう. すなわち,大量のデータを複数のマシンで分割し,それぞれのマシンで推論の計算を行うというような構造である.

    複数の計算機による深層学習モデルを使った推論計算

    このような複数の計算機を同時に走らせるようなアプリケーションをクラウド上で実現するには,どのようにすればよいのだろうか?

    重要なポイントとして, figure_titlefigure_title で起動している複数のマシンは,基本的に全く同一の OS・計算環境を有している点である. ここで,個人のコンピュータで行うようなインストールの操作を,各マシンで行うこともできるが,それは大変な手間であるし,メンテナンスも面倒だろう. すなわち,大規模な計算システムを構築するには,簡単に計算環境を複製できるような仕組みが必要であるということがわかる.

    そのような目的を実現するために使われるのが, Docker とよばれるソフトウェアである.

    Docker とは

    Docker のアイコン

    Docker とは, コンテナ (Container) とよばれる仮想環境下で,ホスト OS とは独立した別の計算環境を走らせるためのソフトウェアである. Docker を使うことで, OS を含めたすべてのプログラムをコンパクトにパッケージングすることが可能になる (パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ). Docker を使うことで,クラウドのサーバー上に瞬時に計算環境を複製することが可能になり, figure_title で見たような複数の計算機を同時に走らせるためのシステムが実現できる.

    Docker は 2013 年に Solomon Hykes らを中心に開発され,それ以降爆発的に普及し,クラウドコンピューティングだけでなく,機械学習・科学計算の文脈などでも欠かすことのできないソフトウェアとなった. Docker はエンタープライズ向けの製品を除き無料で使用することができ,コアの部分は オープンソースプロジェクト として公開されている. Docker は Linux, Windows, Mac いずれの OS でも提供されている. 概念としては, Docker は仮想マシン (Virtual machine; VM) にとても近い. ここでは, VM との対比をしながら,Docker とはなにかを簡単に説明しよう.

    仮想マシン (VM) とは,ホストとなるマシンの上に,仮想化された OS を走らせる技術である (figure_title). VM には ハイパーバイザー (Hypervisor) とよばれるレイヤーが存在する. Hypervisor はまず,物理的な計算機リソース (CPU, RAM, network など) を分割し,仮想化する. たとえば, ホストマシンに物理的な CPU が 4 コアあるとして,ハイパーバイザーはそれを (2,2) 個の組に仮想的に分割することができる. VM 上で起動する OS には,ハイパーバイザーによって仮想化されたハードウェアが割り当てられる. VM 上で起動する OS は基本的に完全に独立であり,たとえば OS-A は OS-B に割り当てられた CPU やメモリー領域にアクセスすることはできない (これを isolation とよぶ). VM を作成するための有名なソフトウェアとしては, VMwareVirtualBoxXen などがある. また,これまで触ってきた EC2 も,基本的に VM 技術を使うことで所望のスペックをもった仮想マシンがユーザーに提示される.

    Docker も, VM と同様に,仮想化された OS をホストの OS 上に走らせるための技術である. VM に対し, Docker ではハードウェアレベルの仮想化は行われておらず,すべての仮想化はソフトウェアレベルで実現されている (figure_title). Docker で走る仮想 OS は,多くの部分をホストの OS に依存しており,結果として非常にコンパクトである. その結果, Docker で仮想 OS を起動するために要する時間は, VM に比べて圧倒的に早い. また, パッケージ化された環境 (=イメージ) のサイズも完全な OS に比べ圧倒的に小さくなるので,ネットワークを通じたやり取りが非常に高速化される点も重要である 加えて, VM のいくつかの実装では,メタル (仮想化マシンに対して,物理的なハードウェア上で直接起動する場合のこと) と比べ,ハイパーバイザーレイヤーでのオーバーヘッドなどにより性能が低下することが知られているが, Docker ではメタルとほぼ同様の性能を引き出すことができるとされている.

    その他, VM との相違点などはたくさんあるのだが,ここではこれ以上詳細には立ち入らない. 大事なのは, Docker とはとてもコンパクトかつハイパフォーマンスな仮想計算環境を作るツールである,という点である. その手軽さゆえに,2013 年の登場以降,クラウドシステムでの利用が急速に増加し,現代のクラウドでは欠くことのできない中心的な技術になっている.

    Docker (左) と VM (右) の比較 (画像出典: https://www.docker.com/blog/containers-replacing-virtual-machines/)

    職業的プログラマーにとっての"三種の神器"とはなんだろうか? 多様な意見があると思うが,筆者は Git, Vim そして Docker を挙げたい.

    Git は多くの読者がご存じの通り,コードの変更を追跡するためのシステムである. Linux の作成者である Linus Torvalds によって 2005 年に誕生した. チームでの開発を進める際には欠かせないツールだ.

    Vim は 1991 年から 30 年以上の間プログラマーたちに愛されてきたテキストエディターである. Stackoverflow が行った 2019 年のアンケート によると,開発環境の部門で 5 位の人気を獲得している. たくさんのショートカットと様々なカスタム設定が提供されているので,初見の人にはなかなかハードルが高いが,一度マスターすれば他のモダンなエディターや統合開発環境に負けない,あるいはそれ以上の開発体験を実現することができる.

    これらの十年以上の歴史あるツールに並んで,第三番目の三種の神器として挙げたいのが Docker だ. Docker はプログラマーの開発のワークフローを一変させた. たとえば,プロジェクトごとに Docker イメージを作成することで,どの OS・コンピュータ でも全く同じ計算環境で開発・テストを実行することができるようになった. また, DevOpsCI / CD (Continuous Integration / Continuous Deployment) といった最近の開発ワークフローも Docker のようなコンテナ技術の存在に立脚している. さらにはサーバーレスコンピューティング (Serverless architecture) といった概念も,コンテナ技術の生んだ大きな技術革新といえる.

    あなたにとっての三種の神器はなんだろうか? また,これからの未来ではどんな新しいツールが三種の神器としてプログラマーのワークフローを革新していくだろうか?

    Docker チュートリアル

    Docker とはなにかを理解するためには,実際に触って動かしてみるのが一番有効な手立てである. ここでは, Docker の簡単なチュートリアルを行っていく.

    Docker のインストールについては, Docker のインストール および 公式のドキュメンテーション を参照してもらいたい. Docker のインストールが完了している前提で,以下は話を進めるものとする.

    Docker 用語集

    Docker を使い始めるに当たり,最初に主要な用語を解説しよう. 次のパラグラフで太字で強調された用語を頭に入れた上で,続くチュートリアルに取り組んでいただきたい.

    Docker を起動する際の大まかなステップを示したのが figure_title である. パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ. イメージは, Docker Hub などのリポジトリで配布されているものをダウンロードするか,自分でカスタムのイメージを作成することも可能である. イメージを作成するための”レシピ”を記述したファイルが Dockerfile である. Dockerfile からイメージを作成する操作を build とよぶ. イメージがホストマシンのメモリにロードされ,起動状態にある計算環境のことを コンテナ (Container) とよぶ. Container を起動するために使用されるコマンドが run である.

    Image と Container

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, Hands-on #2: AWS でディープラーニングを実践 でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    sh
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    python
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    -
    -RUN apt-get update \
    -    && apt-get install nano
    -
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    -
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    -
    -#
    -RUN npm install -g aws-cdk@1.100
    -
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    -
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    -
    -RUN apt-get update \
    -    && apt-get install nano
    -
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    -
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    -
    -#
    -RUN npm install -g aws-cdk@1.100
    -
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    -
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    Singularity は科学計算や HPC (High Performance Computing) の分野で人気の高いコンテナプラットフォームである. Singularity では大学・研究機関の HPC クラスターでの運用に適したような設計が施されている. たとえば, Docker は基本的には root 権限で実行されるのに対し, Singularity はユーザー権限 (コマンドを実行したユーザー自身) でプログラムが実行される. root 権限での実行は Web サーバーのように個人・企業がある特定のサービスのために運用するサーバーでは問題ないが,多数のユーザーが多様な目的で計算を実行する HPC クラスターでは問題となる. また,Singularity は独自のイメージの作成方法・エコシステムをもっているが, Docker イメージを Singularity のイメージに変換し実行する機能も有している.

    podman は Red Hat 社によって開発されたもう一つのコンテナプラットフォームである. podman は基本的に Docker と同一のコマンドを採用しているが,実装は Red Hat によってスクラッチから行われた. podman では, Singularity と同様にユーザー権限でのプログラムの実行を可能であり,クラウドおよび HPC の両方の環境に対応するコンテナプラットフォームを目指して作られた. また,その名前にあるとおり pod とよばれる独自の概念が導入されている.

    著者の個人的な意見としては,現時点では Docker をマスターしておけば当面は困ることはないと考えるが,興味のある読者はぜひこれらのツールも試してみてはいかがだろうか?

    Elastic Container Service (ECS)

    ECS のアイコン

    ここまでに説明してきたように, Docker を使うことで仮想計算環境を簡単に複製・起動することが可能になる. 本章の最後の話題として, AWS 上で Docker を使った計算システムを構築する方法を解説しよう.

    Elastic Container Service (ECS) とは, Docker を使った計算機クラスターを AWS 上に作成するためのツールである (figure_title). ECS を使用することで, Docker にパッケージされたアプリケーションを計算機クラスターに投入したり,計算機クラスターのインスタンスを追加・削除する操作 (=スケーリング) を行うことができる.

    ECS の概要を示したのが figure_title である. ECS は,タスク (Task) と呼ばれる単位で管理された計算ジョブを受け付ける. システムにタスクが投入されると,ECS は最初にタスクで指定された Docker イメージを外部レジストリからダウンロードしてくる. 外部レジストリとしては, Docker Hub や AWS 独自の Docker レジストリである ECR (Elastic Container Registry) を指定することができる.

    ECS の次の重要な役割はタスクの配置である. あらかじめ定義されたクラスター内で,計算負荷が小さい仮想インスタンスを選び出し,そこに Docker イメージを配置することで指定された計算タスクが開始される. "計算負荷が小さい仮想インスタンスを選び出す" と言ったが,具体的にどのような戦略・ポリシーでこの選択を行うかは,ユーザーの指定したパラメータに従う.

    また,クラスターのスケーリングも ECS における重要な概念である. スケーリングとは,クラスター内のインスタンスの計算負荷をモニタリングし,計算負荷に応じてインスタンスの起動・停止を行う操作を指す. クラスター全体の計算負荷が指定された閾値 (たとえば 80%の稼働率) を超えていた場合,新たな仮想インスタンスをクラスター内に立ち上げる操作を scale-out (スケールアウト) とよび, 負荷が減った場合に不要なインスタンスを停止する操作を scale-in (スケールイン) とよぶ. クラスターのスケーリングは, ECS がほかの AWS のサービスと連携することで実現される. 具体的には, EC2 の Auto scaling group (ASG)Fargate の2つの選択肢が多くの場合選択される. ASG については Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する, Fargate については Hands-on #3: AWS で自動質問回答ボットを走らせる でより詳細に解説する.

    これら一連のタスクの管理を, ECS は自動でやってくれる. クラスターのスケーリングやタスクの配置に関してのパラメータを一度指定してしまえば,ユーザーは (ほとんどなにも考えずに) 大量のタスクを投入することができる. クラスターのスケーリングによってタスクの量にちょうど十分なだけのインスタンスが起動し,タスクが完了した後は不要なインスタンスはすべて停止される.

    さて,ここまで説明的な話が続いてしまったが,次章からは早速 Docker と AWS を使って大規模な並列計算システムを構築していこう!

    ECS の概要

    Hands-on #3: AWS で自動質問回答ボットを走らせる

    ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.

    通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 (Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.

    Fargate

    ハンズオンに入っていく前に, Fargate という AWS の機能を知っておく必要がある (figure_title).

    Fargate のアイコン

    ECS の概要を示した figure_title をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. EC2 あるいは Fargate のいずれかである. EC2 を用いた場合は,先の章 (Hands-on #1: 初めての EC2 インスタンスを起動する, Hands-on #2: AWS でディープラーニングを実践) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 (Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) で説明することにする.

    Fargate とは, ECS での利用に特化して設計された,コンテナを使用した計算タスクを走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は docker run のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.

    Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは 公式ドキュメンテーション "Amazon ECS on AWS Fargate" 参照). クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.

    以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.

    厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.

    準備

    ハンズオンのソースコードは GitHub の handson/qa-bot にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    sh
    answer: 1921
    answer: 1921

    人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

    今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    sh
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    sh
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    出力:

    sh
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    今回提供する Q-A ボットの Docker のソースコードは https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile にある.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,以下のような設計である.

    • クライアントは,質問を AWS 上のアプリケーションに送信する.

    • 質問のタスクは ECS によって処理される.

    • ECS は, Docker Hub から,イメージをダウンロードする.

    • 次に,ECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.

      • このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.
    • ジョブが実行される.

    • ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.

    • 最後に,クライアントは DynamoDB から質問への回答を読み取る.

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    sh
    class EcsClusterQaBot(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    -
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    -
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    -
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    -
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    class EcsClusterQaBot(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    -
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    -
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    -
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    -
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

    • ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.

    • ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.

    • ここで,実行するタスクを定義している (task definition).

    • ここで, タスクの実行で使用する Docker イメージを定義している.

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    sh
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    -
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    -
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    -
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    -
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.

    このコードで cpu=1024 と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は 公式ドキュメンテーション "Amazon ECS on AWS Fargate" を参照のこと.

    CPU ユニットと 指定可能なメモリー量の換算表

    CPU ユニット

    メモリーの値

    256 (.25 vCPU)

    0.5 GB, 1 GB, 2 GB

    512 (.5 vCPU)

    1 GB, 2 GB, 3 GB, 4 GB

    1024 (1 vCPU)

    2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB

    2048 (2 vCPU)

    Between 4 GB and 16 GB in 1-GB increments

    4096 (4 vCPU)

    Between 8 GB and 30 GB in 1-GB increments

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. figure_title で, FARGATE という文字の下に 0 Running tasks, 0 Pending tasks と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.

    ECS コンソール画面

    続いて,この画面の左のメニューバーから Task Definitions という項目を見つけ,クリックしよう. 移動した先のページで EcsClusterQaBotEcsClusterQaBotTaskDefXXXX という項目が見つかるので,開く. 開いた先のページをスクロールすると figure_title に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.

    Task definition の確認

    タスクの実行

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, "Tasks" という名前のタブがあるので,それを開く (figure_title). すると,実行中のタスクの一覧が表示されるだろう.

    ECS のタスクの実行状況をモニタリング

    figure_title で見て取れるように, "Last status = Pending" となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.

    しばらく待つうちに, Status が "RUNNING" に遷移し,計算が始まる. 計算が終わると, Status は "STOPPED" に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.

    figure_title の画面から, "Task" の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (figure_title). "Last status", "Platform version" など,タスクの情報が表示されている. また, "Logs" のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.

    質問タスクの実行結果

    さて, run_task.py を実行したコマンドラインに戻ってきてみると, figure_title のような出力が得られているはずである. "Momotaro" という正しい回答が返ってきている!

    質問タスクの実行結果

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する

    ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

    本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

    Auto scaling groups (ASG)

    ハンズオンに入っていく前に, Auto scaling groups (ASG) とよばれる EC2 の概念を知っておく必要がある.

    ECS の概要を示した figure_title を振り返って見てほしい. 前章 (Hands-on #3: AWS で自動質問回答ボットを走らせる) でも説明したが, ECS のクラスターで計算を担う実体としては EC2 と Fargate を指定することができる. Fargate については前章で記述した. Fargate を用いると,自在にスケールする計算環境をとても簡単な設定で構築することができた. しかし, GPU を利用することができないなど,いくつかの制約があった. EC2 を使用した計算環境を指定することで,プログラミングの複雑度は増すが, GPU やその他のより高度かつ複雑な設定を伴ったクラスターを構築することができる.

    EC2 クラスターには ASG と呼ばれるサービスが配置される. ASG は複数の EC2 インスタンスをロジカルな単位でグループ化することでクラスターを構成する. ASG はクラスター内に新しいインスタンスを起動する,あるいは不要になったインスタンスを停止するなどのスケーリングを担う. ASG で重要な概念として, desired capacity, minimum capacity, maximum capacity というパラメータがある. minimum capacity, maximum capacity は,それぞれクラスター内に配置できるインスタンスの数の最小値・最大値を指定するパラメータである. 前者は,クラスターに負荷がかかっていない場合でもアイドリング状態にあるインスタンスを維持することで,急に負荷が増大した時などのバッファーとして作用することができる. 後者は,負荷が急に増えたときに,過剰な数のインスタンスが起動する事態を防ぎ,経済的なコストの上限を定める役割を果たす.

    desired capacity が,その時々でシステムが要求するインスタンスの数を指定する. desired capacity は,例えば 24 時間のリズムに合わせてインスタンスの数を増減させる (昼は多く夜は少なくなど) などの決まったスケジュールに基づいた設定を適用することができる. あるいはクラスター全体にかかっている負荷に応じて, desired capacity を動的に制御することも可能である. どのような基準でクラスターのスケーリングを行うかを定めるルールのことを,スケーリングポリシーとよぶ. たとえば,クラスター全体の稼働率 (負荷) を常に 80% に維持する,などのスケーリングポリシーが想定できる. この場合,クラスター全体の負荷が 80%を下回ったときにはクラスターからインスタンスが削除され,80%を超える (あるいは超えると予測される) 場合はインスタンスを追加する,という操作が ASG によって自動的に行われる.

    上記のようなパラメータを検討し,ユーザーは ASG を作成する. ASG を作成したのち, ECS との連携をプログラムしてあげることで, ECS を介して ASG による EC2 クラスターにタスクを投入することが可能になる.

    AWS Batch

    AWS Batch のアイコン

    先に説明したように, ECS と ASG を組み合わせることで,所望の計算クラスターを構築することが可能である. しかしながら, ECS と ASG にはかなり込み入った設定が必要であり,初心者にとっても経験者にとってもなかなか面倒なプログラミングが要求される. そこで, ECS と ASG によるクラスターの設計を自動化してくれるサービスが提供されている. それが AWS Batch である.

    AWS Batch はその名のとおりバッチ (Batch) 化されたジョブ (入力データだけが異なる独立した演算が繰り返し実行されること) を想定している. 多くの科学計算や機械学習がバッチ計算に当てはまる. たとえば,初期値のパラメータを変えて複数のシミュレーションを走らせる,といったケースだ. AWS Batch を用いることの利点は,クラスターのスケーリングやジョブの割り振りはすべて自動で実行され, ユーザーはクラウドの舞台裏の詳細を気にすることなく,大量のジョブを投入できるシステムが手に入る点である. が,知識として背後では ECS/ASG/EC2 の三つ巴が協調して動作しているという点は知っておいてほしい.

    AWS Batch では,ジョブの投入・管理をスムーズに行うため,次のような概念が定義されている (figure_title). まず, ジョブ (Job) というのが,AWS Batch によって実行される一つの計算の単位である. Job definitions とはジョブの内容を定義するものであり,これには実行されるべき Docker のイメージのアドレスや,割り当てる CPU・RAM の容量,環境変数などの設定が含まれる. Job definition に基づいて個々のジョブが実行される. ジョブが実行されると,ジョブは Job queues に入る. Job queues とは,実行待ち状態にあるジョブの列のことであり,時間的に最も先頭に投入されたジョブが最初に実行される. また,複数の queue を配置し, queue ごとに priority (優先度) を設定することが可能であり, priority の高い queue に溜まったジョブが優先的に実行される (筆者はこれをディズニーランドの"ファストパス"を連想して捉えている). Compute environment とは,先述したクラスターとほぼ同義の概念であり,計算が実行される場所 (EC2 や Fargate からなるクラスター) を指す. Compute environment には,使用する EC2 のインスタンスタイプや同時に起動するインスタンス数の上限などの簡易なスケーリングポリシーが指定されている. Job queues は Compute environment の空き状況を監視しており, それに応じてジョブを Compute environment に投下する.

    以上が AWS Batch を使用するうえで理解しておかなければならない概念であるが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは,実際に自分で手を動かしながら学んでいこう.

    AWS Batch の主要な概念

    EC2 or Fargate?

    ECS でクラスターを構成する際,計算を実行する場として EC2 と Fargate の二つの選択肢があることを説明した. それぞれ長所と短所を抱えているのだが,どのような場合にどちらを使うべきだろうか? それを検討するため,まずは table_title を見てみよう. これは EC2 と Fargate の特徴をまとめたものである. 説明の都合上,大幅な粗視化が行われている点は留意していただきたい.

    EC2 vs Fargate
    EC2Fargate

    Compute capacity

    Medium to large

    Small to medium

    GPU

    Yes

    No

    Launch speed

    Slow

    Fast

    Task placement flexibility

    Low

    High

    Programming complexity

    High

    Low

    これまでに見てきたように, EC2 は最大の CPU 数・メモリーサイズが大きかったり, GPU を利用できたりするなど,単一のインスタンスでの計算能力は高い. 対して, Fargate は単一インスタンスの最大 CPU 数は 4 コアが上限である. その一方で,インスタンスの起動に要する時間は Fargate のほうが圧倒的に早く,より俊敏にクラスターのスケーリングを行うことができる. また,タスクをクラスターに投入する際のフレキシビリティも Fargate のほうが高い. フレキシビリティというのは,例えば一つのインスタンスで 2 つ以上のコンテナを走らせる,などの状況である. 単位 CPU あたりで処理されるタスクの数を最大化する際には,このような設計がしばしば採用される. プログラミングの複雑さという観点からは, Fargate のほうが一般的にシンプルな実装になる.

    このように, EC2 と Fargate は互いに相補的な特性を有しており,アプリケーションによって最適な計算環境は検討される必要がある. また,EC2 と Fargate を両方用いたハイブリッドクラスターというのも定義可能であり,そのような選択肢もしばしば用いられる.

    準備

    ハンズオンのソースコードは GitHub の handson/aws-batch にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,アメリカ東部 (us-east-1) リージョンでは 0.526 $/hour のコストが発生する. 東京 (ap-northeast-1) を選択した場合は 0.71 $/hour のコストが発生する.

    準備 でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, 実践ディープラーニング! MNIST 手書き数字認識タスク で扱った MNIST 手書き文字認識の問題を再度取り上げよう. 実践ディープラーニング! MNIST 手書き数字認識タスク では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    ランダムサーチ法とは,ハイパーパラメータの組をある範囲の中でランダムに抽出し,大量に試行されたランダムな組の中から最適なパラメータの組を見出す方法である. すべての可能性を網羅的に探索できるわけではないが,調整すべきパラメータの数が多数ある場合に,グリッドサーチよりも効率的に広い探索空間をカバーすることができる.

    ベイズ最適化を用いた方法では,過去の探索結果から次にどの組み合わせを探索すべきかという指標を計算し,次に探索するパラメータを決定する. これにより,理論的にはグリッドサーチやランダムサーチ法よりも少ない試行回数で最適なパラメータにたどり着くことができる.

    並列化の観点でいうと,グリッドサーチとランダムサーチは各ハイパーパラメータの組の計算は独立に実行することができるため並列化が容易である. このように独立したジョブとして分割・並列化可能な問題を Embarrassingly parallel な問題とよぶ (直訳すると"恥ずかしいほど並列化可能な問題",ということになる). Embarrassingly parallel な問題はクラウドの強力な計算リソースを用いることで,非常なシンプルな実装で解くことができる. この章ではこのようなタイプの並列計算を取り上げる.

    一方,ベイズ最適化による方法は,過去の結果をもとに次の探索が決定されるので,並列化はそれほど単純ではない. 最近では optuna などのハイパーパラメータ探索のためのライブラリが発達しており,ベイズ最適化の数理的な処理を自動で実行してくれるので便利である. これらのライブラリを使うと,もし一台のコンピュータ (ノード) の中に複数の GPU が存在する場合は,並列に計算を実行することができる. しかしながら,一台のノードにとどまらず,複数のノードをまたいだ並列化は,高度なプログラミングテクニックが必要とされるだけでなく,ノード間の接続様式などクラウドのアーキテクチャにも深く依存するものである. 本書ではここまで高度なクラウドの使用方法には立ち入らない.

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に 実践ディープラーニング! MNIST 手書き数字認識タスク のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    sh
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. Hands-on #2: AWS でディープラーニングを実践 のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    sh
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドでは,--gpus all というパラメータが加わった.

    CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

    (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

    これはオーバーフィッティングとよばれる現象で,ニューラルネットが訓練データに過度に最適化され,訓練データの外のデータに対しての精度 (汎化性能) が向上していないことを示している. このような場合の対処法として, Early stopping とよばれるテクニックが知られている. Early stopping とは,検証データの Loss を追跡し,それが減少から増加に転じるエポックで学習をうち止め,そのエポックでのウェイトパラメータを採用する,というものである. 本ハンズオンでも, Early stopping によって訓練の終了を判断し,モデルの性能評価を行っていく.

    MNIST 手書き文字データセットでは,訓練データとして 60,000 枚,テストデータとして 10,000 枚の画像が与えられている. 本ハンズオンで使用するコードでは,訓練データのうち 80% の 48,000 枚を訓練データとして使用し,残り 20% の 12,000 枚を検証データとして用いている. 詳しくはソースコードを参照のこと.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントは,あるハイパーパラメータの組を指定して Batch にジョブを提出する

    • Batch はジョブを受け取ると, EC2 からなるクラスターで計算を実行する

    • クラスター内では g4dn.xlarge インスタンスが起動する

    • Docker イメージは, AWS 内に用意された ECR (Elastic Container Registry) から取得される

    • 複数のジョブが投下された場合は,その数だけのインスタンスが起動し並列に実行される

    • 各ジョブによる計算の結果は S3 に保存される

    • 最後にクライアントは S3 から結果をダウンロードし,最適なハイパーパラメータの組を決定する

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    python
    class SimpleBatch(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    -
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    -
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    -
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    -
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    -
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    -
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    class SimpleBatch(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    -
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    -
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    -
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    -
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    -
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    -
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    • で,計算結果を保存するための S3 バケットを用意している

    • で, Compute environment を定義している. ここでは g4dn.xlarge のインスタンスタイプを使用するとし,最大の vCPU 使用数は 64 と指定している. また,最小の vCPU は 0 である. 今回は,負荷がかかっていないときにアイドリング状態にあるインスタンスを用意する利点は全くないので,ここは 0 にするのが望ましい.

    • で, <2> で作成した Compute environment と紐付いた Job queue を定義している.

    • で,ジョブが計算結果を S3 に書き込むことができるよう, IAM ロールを定義している. (IAM とはリソースがもつ権限を管理する仕組みである.詳しくは AWS における権限の管理 (IAM) を参照)

    • では, Docker image を配置するための ECR を定義している.

    • で Job definition を作成している. ここでは,4 vCPU, 12000 MB (=12GB) の RAM を使用するように指定している. また,今後必要となる環境変数 (BUCKET_NAME) を設定している. さらに, <4> で作った IAM を付与している.

    g4dn.xlarge は 1 台あたり 4 vCPU が割り当てられている. このプログラムでは Compute environment の maximum vCPUs を 64 と指定しているので,最大で 16 台のインスタンスが同時に起動することになる. ここで maxium vCPUs を 64 に限定しているのは,なんらかのミスで意図せぬジョブを大量にクラスターに投入してしまった事態で,高額の AWS 利用料金が発生するのを防ぐためである. もし,自分のアプリケーションで必要と判断したならば自己責任において 64 よりも大きな数を設定して構わない.

    ここで注意が一点ある. AWS では各アカウントごとに EC2 で起動できるインスタンスの上限が設定されている. この上限は AWS コンソールにログインし, EC2 コンソールの左側メニューバーの Limits をクリックすることで確認できる (figure_title). g4dn.xlarge (EC2 の区分でいうと G ファミリーに属する) の制限を確認するには, Running On-Demand All G instances という名前の項目を見る. ここにある数字が, AWS によって課されたアカウントの上限であり,この上限を超えたインスタンスを起動することはできない. もし,自分の用途に対して上限が低すぎる場合は,上限の緩和申請を行うことができる. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    EC2コンソールから各種の上限を確認する

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    次に,Job queue overview にある SimpleBatch-queue という項目に注目してほしい. ここでは実行待ちのジョブ・実行中のジョブ・実行が完了したジョブを一覧で確認することができる. PENDING, RUNNING, SUCCEEDED, FAILED などのカラムがあることが確認できる.ジョブが進行するにつれて,ジョブの状態がこのカラムにしたがって遷移していく. 後でジョブを実際にサブミットしたときに戻ってこよう.

    最後に,今回作成した Job definition を確認しよう. 左側のメニューから Job definitions を選択し,次の画面で SimpleBatchjob-definition という項目を見つけて開く. ここから Job definition の詳細を閲覧することができる (figure_title). 中でも重要な情報としては, vCPUs, Memory, GPU がそれぞれ Docker に割り当てられる vCPU・メモリー・ GPU の量を規定している. また, Image と書いてあるところに,ジョブで使用される Docker イメージが指定されている. ここでは, ECR のレポジトリを参照している. 現時点ではこの ECR は空である. 次のステップとして,この ECR にイメージを配置する作業を行おう.

    AWS Batch から Job definition を確認

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン (Hands-on #3: AWS で自動質問回答ボットを走らせる) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    python
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    -
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    -
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    • で,新規の ECR を作成している.

    • で Job definition を定義する中で,イメージを <1> で作った ECR から取得するように指定している. これと同時に, Job definition には ECR へのアクセス権限が IAM を通じて自動的に付与される.

    さて,スタックをデプロイした時点では, ECR は空っぽである. ここに自分のアプリケーションで使う Docker イメージを push してあげる必要がある.

    そのために,まずは AWS コンソールから ECR の画面を開こう (検索バーに Elastic Container Registry と入力すると出てくる). Private というタブを選択すると, simplebatch-repositoryXXXXXX という名前のレポジトリが見つかるだろう (figure_title).

    ECR のコンソール画面

    次に,このレポジトリの名前をクリックするとレポジトリの詳細画面に遷移する. そうしたら,画面右上にある View push commands というボタンをクリックする. すると figure_title のようなポップアップ画面が立ち上がる.

    ECR への push コマンド

    このポップアップ画面で表示されている四つのコマンドを順番に実行していくことで,手元の Docker イメージを ECR に push することができる. push を実行する前に, AWS の認証情報が設定されていることを確認しよう. そのうえで,ハンズオンのソースコードの中にある docker/ という名前のディレクトリに移動する. そうしたら,ポップアップ画面で表示されたコマンドを上から順に実行していく.

    ポップアップで表示されるコマンドの 2 つめを見てみると docker build -t XXXXX . となっている. 最後の . が重要で,これは 現在のディレクトリにある Dockerfile を使ってイメージをビルドせよ という意味である. このような理由で, Dockerfile が置いてあるディレクトリに移動する必要がある.

    四つ目のコマンドは,数 GB あるイメージを ECR にアップロードするので少し時間がかかるかもしれないが,これが完了するとめでたくイメージが ECR に配置されたことになる. もう一度 ECR のコンソールを見てみると,確かにイメージが配置されていることが確認できる (figure_title). これで,AWS Batch を使ってジョブを実行させるための最後の準備が完了した.

    ECR へ image の配置が完了した

    単一のジョブを実行する

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    sh
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    python
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    -
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    -
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    python
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    python
    # [4]
    -submit_job(0.01, 0.1, 100)
    # [4]
    -submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは AWS CLI のインストール), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    AWS Batch でジョブが実行されている様子

    figure_title で赤で囲った箇所に注目してほしい. 一つのジョブが投入されると,それは SUBMITTED という状態を経て RUNNABLE という状態に遷移する. RUNNABLE とは, ジョブを実行するためのインスタンスが Compute environment に不足しているため,新たなインスタンスが起動されるのを待っている状態に相当する. インスタンスの準備が整うと,ジョブの状態は STARTING を経て RUNNING に至る.

    次に,ジョブのステータスが RUNNING のときの Compute environment の Desired vCPU を見てみよう (figure_title で紫で囲った箇所). ここで 4 と表示されているのは, g4dn.xlarge インスタンス一つ分の vCPU の数である. ジョブの投入に応じて,それを実行するのに最低限必要な EC2 インスタンスが起動されたことが確認できる (興味のある人は, EC2 コンソールも同時に覗いてみるとよい).

    しばらく経つと,ジョブの状態は RUNNING から SUCCEEDED (あるいは何らかの理由でエラーが発生したときには FAILED) に遷移する. 今回のハンズオンで使っている MNIST の学習はだいたい 10 分くらいで完了するはずである. ジョブの状態が SUCCEEDED になるまで見届けよう.

    ジョブが完了すると,学習の結果 (エポックごとの Loss と Accuracy を記録した CSV ファイル) は S3 に保存される. AWS コンソールからこれを確認しよう.

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    python
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    python
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    -
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    -
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    -
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    -
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    -
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    -
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    python
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    # [1]
    -import boto3
    -import argparse
    -
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    -
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    python
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    複数のジョブを同時投入したときの Job 一覧

    今度は EC2 コンソールを見てみよう. 左のメニューから Instances を選択すると, figure_title に示すような起動中のインスタンスの一覧が表示される. g4dn.xlarge が 9 台稼働しているのが確認できる. Batch がジョブの投下に合わせて必要な数のインスタンスを起動してくれたのだ!

    複数のジョブを同時投入したときの EC2 インスタンスの一覧

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    python
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    -
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    -
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    -
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    -
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    -
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    -
    -    return df
    -
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    -
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    -
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    -
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    今回のパラメータサーチは勉強用に極めて単純化されたものである点は承知いただきたい.

    たとえば,今回は学習率が 0.1 が最も良いとされたが,それは訓練のエポックを 100 に限定しているからかもしれない. 学習率が低いとその分訓練に必要なエポック数も多くなる. 訓練のエポック数をもっと増やせばまた違った結果が観察される可能性はある.

    また,今回は MNIST の訓練データ 60,000 枚のうち, 48,000 枚を訓練データ,残り 12,000 枚を検証データとして用いた. この分割は乱数を固定してランダムに行ったが,もしこの分割によるデータのバイアスを気にするならば, k 個の異なる学習・検証データの分割をあらかじめ用意して,複数回モデルの評価を行う (k-fold cross-validation) 方法も,より精緻なアプローチとして考えられる.

    以上のようにして, CNN を用いた MNIST 分類モデルのハイパーパラメータの最適化の一連の流れを体験した. AWS Batch を利用することで,比較的少ないプログラミングで,動的に EC2 クラスターを制御し,並列にジョブを処理するシステムが構築できた. ここまで EC2 を使いこなすことができれば,多くの問題を自力で解くことが可能になるだろう!

    スタックの削除

    これにて,本ハンズオンは終了である.最後にスタックを削除しよう. 今回のスタックを削除するにあたり,ECR に配置された Docker のイメージは手動で削除されなければならない (これをしないと, cdk destroy を実行したときにエラーになってしまう. これは CloudFormation の仕様なので従うしかない).

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, Hands-on #2: AWS でディープラーニングを実践 で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを Hands-on #3: AWS で自動質問回答ボットを走らせる を参考に構築する.

    実際,本書ではこの流れに沿って演習を進めてきた. MNIST タスクを解くモデルを,最初 Jupyter Notebook を使用して実験し,そのコードをほとんどそのまま Docker にパッケージし, AWS Batch を用いてハイパーパラメータサーチを行った. このサイクルを繰り返すことで,クラウドを最大限に活用した機械学習アプリケーションの開発を進めることができる.

    クラウドを活用した機械学習アプリケーションの開発フロー

    小括

    ここまでが,本書第二部の内容である. 第一部に引き続き盛りだくさんの内容であったが,ついてこれたであろうか?

    第二部ではまず最初に,深層学習の計算をクラウドで実行するため, GPU 搭載型の EC2 インスタンスの起動について解説した. さらに,ハンズオンでは,クラウドに起動した仮想サーバーを使って MNIST 文字認識タスクを解くニューラルネットを訓練した (Hands-on #2: AWS でディープラーニングを実践).

    また,より大規模な機械学習アプリケーションを作るための手段として, Docker と ECS によるクラスターの初歩を説明した (Docker 入門). その応用として,英語で与えられた文章問題への回答を自動で生成するボットをクラウドに展開した (Hands-on #3: AWS で自動質問回答ボットを走らせる). タスクの投入に応じて動的に計算リソースが作成・削除される様子を実際に体験できただろう.

    さらに, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する では AWS Batch を用いてニューラルネットの学習を並列に実行する方法を紹介した. ここで紹介した方法は,ミニマムであるが,計算機システムを大規模化していくためのエッセンスが網羅されている. これらのハンズオン体験から,クラウド技術を応用してどのように現実世界の問題を解いていくのか,なんとなくイメージが伝わっただろうか?

    本書の第三部では,さらにレベルアップし,サーバーレスアーキテクチャという最新のクラウドの設計手法について解説する. その応用として,ハンズオンでは簡単な SNS サービスをゼロから実装する. 引き続きクラウドの最先端の世界を楽しんでいこう!

    Web サービスの作り方

    ここからが,本書第三部の内容になる. これまでのセクションでは,仮想サーバーをクラウド上に起動し,そこで計算を走らせる方法について解説をしてきた. EC2, ECS, Fargate, Batch などを利用して,動的にスケールするクラスターを構成し,並列にタスクを実行するクラウドシステムを実装してきた. 振り返ると,これまで紹介してきた内容は,自分自身が行いたい計算をクラウドを駆使することで実現する,という用途にフォーカスしていたことに気がつくだろう. 一方で,広く一般の人々に使ってもらえるような計算サービス・データベースを提供する,というのもクラウドの重要な役割として挙げられる.

    本章から始まる第三部では,前回までとは少し方向性を変え,どのようにしてクラウド上にアプリケーションを展開し,広く一般の人に使ってもらうか,という点を講義したいと思う. これを通じて,どのようにして世の中のウェブサービスができ上がっているのかを知り,さらにどうやって自分でそのようなアプリケーションをゼロから構築するのか,という点を学んでもらう. その過程で,サーバーレスアーキテクチャという最新のクラウド設計手法を解説する.

    その前準備として,本章ではどのようにしてウェブサービスが出来上がっているのか,その背後にある技術の概要を解説する. 用語の解説が中心となるが,後のハンズオンを実装するために必須の知識であるので,理解して前に進むよう心がけよう.

    ウェブサービスの仕組み  — Twitter を例に

    あなたがパソコンやスマートフォンから Twitter, Facebook, YouTube などのウェブサービスにアクセスしたとき,実際にどのようなことが行われ,コンテンツが提示されているのだろうか?

    HTTP を通じたサーバーとクライアントのデータのやり取りは,すでに知っている読者も多いだろうし,逆にすべて解説しようとすると紙面が足りないので,ここではエッセンスの説明のみにとどめる. 以降では Twitter を具体例として,背後にあるサーバーとクライアントの間の通信を概説しよう. 概念図としては figure_title のような通信がクライアントとサーバーの間で行われていることになる.

    クライアントと Web サーバーの通信の概念図

    前提として,クライアントとサーバーの通信は HTTP (Hypertext Transfer Protocol) を使って行われる. また,最近では,暗号化された HTTP である HTTPS (HTTPS (Hypertext Transfer Protocol Secure)) を用いることがスタンダードになってきている. 第一のステップとして,クライアントは HTTP(S) 通信によってサーバーから静的なコンテンツを取得する. 静的なコンテンツとは, HTML (Hyptertext Markup Language) で記述されたウェブページの文書本体, CSS (Cascading Style Sheets) で記述されたページのデザインやレイアウトファイル,そして JavaScript (JS) で記述されたページの動的な挙動を定義したプログラム,が含まれる. Twitter を含む現代的なウェブアプリケーションの設計では,この静的なファイル群はページの”枠”を定義するだけで,中身となるコンテンツ (例: ツイートの一覧) は別途 API (Application Programming Interface) によって取得されなければならない. そこで,クライアントは先のステップで取得された JavaScript で定義されたプログラムに従って,サーバーに API を送信し,ツイートや画像データを取得する. この際,テキストデータのやり取りには JSON (JavaScript Object Notation) というフォーマットが用いられることが多い. 画像や動画などのコンテンツも同様に API により取得される. このようにして取得されたテキストや画像が,HTML の文書に埋め込まれることで,最終的にユーザーに提示されるページが完成するのである. また,新しいツイートを投稿するときにも,クライアントから API を通じてサーバーのデータベースにデータが書き込まれる.

    REST API

    API (Application Programming Interface) とはこれまで何度も出てきた言葉であるが,ここではよりフォーマルな定義付けを行う. API とはあるソフトウェア・アプリケーションが,外部のソフトウェアに対してコマンドやデータをやり取りするための媒介の一般的総称である. とくに,ウェブサービスの文脈では,サーバーが外界に対して提示しているコマンドの一覧のことを意味する. クライアントは,提示されている API から適切なコマンドを使うことによって,所望のデータを取得したり,あるいはサーバーにデータを送信したりする.

    とくに,ウェブの文脈では REST (Representational State Transfer) とよばれる設計思想に基づいた API が現在では最も一般的に使われている. REST の設計指針に従った API のことを REST API あるいは RESTful API とよんだりする.

    REST API は, figure_title に示したような MethodURI (Universal Resource Identifier) の組からなる.

    REST API

    Method (メソッド) とは,どのような操作を行いたいかを抽象的に表す,"動詞" として捉えることができる. メソッドには HTTP 規格で定義された 9 個の動詞 (verb) を使用することができる. この中でも, GET, POST, PUT, PATCH, DELETE の 5 個が最も頻繁に使用される (table_title). この 5 つのメソッドによる操作を総称して CRUD (create, read, update, and delete) とよぶ.

    REST API Methods
    メソッド意図される動作

    GET

    要素を取得する

    POST

    新しい要素を作成する

    PUT

    既存の要素を新しい要素と置き換える

    PATCH

    既存の要素の一部を更新する

    DELETE

    要素を削除する

    一方, URI は操作が行われる対象,すなわち "目的語" を表す. ウェブの文脈では操作が行われる対象のことをしばしば リソース とよぶ. URI は多くの場合 http または https から始まるウェブサーバーのアドレスから始まり, / (スラッシュ) 以降に所望のリソースのパスが指定される. figure_title の例で言えば, https://api.twitter.com というアドレスの /1.1/status/home_timeline というリソースを取得 (GET) せよ,という意味になる (なお,ここで 1.1 という数字は API のバージョンを示している). この API リクエストによって,ユーザーのホームのタイムラインのツイートの一覧が取得される.

    REST API のメソッドには, table_title で挙げたもの以外に, HTTP プロトコルで定義されているほかのメソッド (OPTIONS, TRACE など) を用いることもできるが,あまり一般的ではない.

    また,これらのメソッドだけでは動詞として表現しきれないこともあるが, URI の名前でより意味を明確にすることもある. メソッドの使い方も,要素を削除する際は必ず DELETE を使わなければならない,という決まりもなく,たとえば, Twitter API でツイートを消す API は POST statuses/destroy/:id で定義されている. 最終的には,各ウェブサービスが公開している API ドキュメンテーションを読んで,それぞれの API がどんな操作をするのかを調べる必要がある.

    REST の概念は 2000 年代初頭に確立され,今日の API 設計のスタンダードとなった. 一方で,ウェブのテクノロジーが進歩するにつれて,新たな API の設計アプローチの需要も高まっている. 近年とくに人気を集めているのが, GraphQL と呼ばれる API の設計方法である. GraphQL は Facebook 社によって最初に作られ,現在は GraghQL Foundation によって維持と更新がされている. GraphQL を使用すると,クライアントは REST と比較してより柔軟性の高いデータのクエリを行うことができるなど,いくつかの利点がある. キーワードだけでも知っておくと,今後役に立つだろう.

    Twitter API

    もう少し具体的にウェブサービスの API を体験する目的で,ここでは Twitter の API を見てみよう. Twitter が提供している API の一覧は Twitter の Developer Documentation で見ることができる. いくつかの代表的な API を table_title にまとめた.

    Twitter API
    エンドポイント動作

    GET statuses/home_timeline

    ホームのタイムラインのツイートの一覧を取得する.

    GET statuses/show/:id

    :id で指定されたツイートの詳細情報を取得する.

    GET search

    ツイートの検索を実行する.

    POST statuses/update

    新しいツイートを投稿する.

    POST media/upload

    画像をアップロードする

    POST statuses/destroy/:id

    :id で指定されたツイートを削除する.

    POST statuses/retweet/:id

    :id で指定されたツイートをリツイートする.

    POST statuses/unretweet/:id

    :id で指定されたツイートのリツイートを取り消す.

    POST favorites/create

    選択したツイートを"いいね"する.

    POST favorites/destroy

    選択したツイートを"いいね"を取り消す.

    この API リストをもとに, Twitter のアプリまたはウェブサイトを開いたときに起こるクライアントとサーバーの通信をシミュレートしてみよう.

    ユーザーが Twitter を開くと,まず最初に GET statuses/home_timeline の API リクエストによって,ユーザーのホームのタイムラインのツイートのリストが取得される. 個々のツイートは JSON 形式のデータになっており, id, text, user, coordinates, entities などの属性を含む. id はツイートに固有な ID を表し, text はツイートの本文を含んでいる. user はツイートを投稿したユーザーの名前やプロフィール画像の URL などを含んだ JSON データになっている. coordinates にはツイートが発信された地理的な座標が記録されている. また, entities にはツイートに関連するメディアファイル (画像など) のリンクなどの情報が埋め込まれている. GET statuses/home_timeline からは直近のツイートのリスト (リストが長すぎる場合は途中で切られたもの) が取得される. もしツイートの ID を知っている場合は GET statuses/show/:id を呼ぶことによって, :id パラメータで指定された特定のツイートを取得することができる.

    ツイートの検索を行うためには GET search API を使用する. この API には,ツイートに含まれる単語や,ハッシュタグ,ツイートの発信された日時や場所など,様々なクエリの条件を渡すことができる. API からは, GET statuses/home_timeline などと同様, JSON 形式のツイートのデータが返される.

    ユーザーが新しいツイートを投稿するには POST statuses/update のエンドポイントを利用する. POST statuses/update には,ツイートの文章や,リプライの場合はリプライ先のツイートの ID などのデータを送信する. また,ツイートに画像データを添付したい場合は, POST media/upload を併せて使用する. ツイートの削除を行うには, POST statuses/destroy/:id を用いる.

    そのほか,頻繁に行われる操作としては, POST statuses/retweet/:idPOST statuses/unretweet/:id がある. これらは, :id で指定されるツイートに対して,それぞれリツイートを実行あるいは取り消すための API である. また, POST favorites/createPOST favorites/destroy を使用することによって,選択されたツイートに"いいね"を追加したり,取り消したりする操作を行う.

    このような一連の操作が, Twitter のアプリの背後では行われている. また,自分自身でボットを作成したい場合は,これらの API を適切に組み合わせ,カスタムのプログラムを書くことで実現される.

    このように, API はあらゆるウェブサービスを作るうえで一番基礎となる要素である. 次からの章では本章で紹介した用語が何度も出てくるので,頭の片隅に置いたうえで読み進めていただきたい.

    Serverless architecture

    サーバーレスアーキテクチャ (Serverless architecture) あるいは サーバーレスコンピューティング (Serverless computing) とは,従来とは全く異なるアプローチに基づくクラウドシステムの設計方法である. 歴史的には, AWS が 2014 年に発表した Lamba がサーバーレスアーキテクチャの先駆けとされている. その後, Google や Microsoft などのクラウドプラットフォームも同様の機能の提供を開始している. サーバーレスアーキテクチャの利点は,スケーラブルなクラウドシステムを安価かつ簡易に作成できる点であり,近年いたるところで導入が進んでいる.

    Serverless とは,文字どおりの意味としてはサーバーなしで計算をするということになるが,それは一体どういう意味だろうか? サーバーレスについて説明するためには,まずは従来的な, "serverful" とよばれるようなシステムについて解説しなければならない.

    Serverful クラウド (従来型)

    従来的なクラウドシステムのスケッチを figure_title に示す. クライアントから送信されたリクエストは,最初に API サーバーに送られる. API サーバーでは,リクエストの内容に応じてタスクが実行される. タスクには,API サーバーだけで完結できるものもあるが,多くの場合,データベースの読み書きが必要である. データベースには,データベース専用の独立したサーバーマシンが用いられることが一般的である. また,画像や動画などの容量の大きいデータは,また別のストレージサーバーに保存されることが多い. これらの API サーバー,データベースサーバー,ストレージサーバーはそれぞれ独立したサーバーマシンであり, AWS の言葉では EC2 による仮想インスタンスを想定してもらったらよい.

    多くのウェブサービスでは,多数のクライアントからのリクエストを処理するため,複数のサーバーマシンがクラウド内で起動し,負荷を分散するような設計がなされている. クライアントから来たリクエストを計算容量に余裕のあるサーバーに振り分けるような操作を Load balancing とよび,そのような操作を担当するマシンのことを Load balancer という.

    計算負荷を分散する目的で多数のインスタンスを起動するのはよいのだが,計算負荷が小さすぎてアイドリング状態にあるようではコストと電力の無駄遣いである. したがって,すべてのサーバーが常に目標とする計算負荷を維持するよう,計算の負荷に応じてクラスター内の仮想サーバーの数を動的に増減させるような仕組みが必要である. そのような仕組みをクラスターのスケーリングとよび,負荷の増大に応答して新しい仮想インスタンスをクラスターに追加する操作を scale-out,負荷の減少に応答してインスタンスをシャットダウンする操作を scale-in とよぶ. クラスターのスケーリングは, API サーバーではもちろんのこと,データベースサーバー・ストレージサーバーでも必要になる. ストレージサーバーでは,例えば頻繁にアクセスされるデータはキャッシュ領域に保存したり,データのコピーを複数作るなどのスケーリングが行われる. データベースサーバーも同様に,頻繁にアクセスされるデータのアクセスがパンクしてしまわないよう,分散的な処理が必要となる. このように,クラウドシステム内すべての箇所で,負荷が均一になるような調整が必要であり,開発者は多くの時間をそのチューニングに費やさなければならない. また,サービスの利用者の数などに応じてスケーリングの設定は常に見直される必要があり,継続的な開発が要求される.

    さらに問題を複雑にするのは,API サーバーで処理されるべきタスクが,非一様な点である. 非一様であるとは,たとえばタスク A は 3000 ミリ秒の実行時間と 512MB のメモリーを消費し,別のタスク B は 1000 ミリ秒の実行時間と 128MB のメモリーを消費する,というような状況を指している. 一つのサーバーマシンが計算負荷が異なる複数のタスクを処理する場合,クラスターのスケーリングはより複雑になる. この状況をシンプルにするために,1サーバーで実行するタスクは1種類に限る,という設計も可能であるが,そうするとで生まれる弊害も多い (ほとんど使われないタスクに対してもサーバー一台をまるまる割り当てなければならない = ほとんどアイドリング状態になってしまう,など).

    Serverful なクラウドシステム

    Serverless クラウドへ

    Serverful クラウド (従来型) で議論したように,クラスターのスケーリングはクラウドシステムの経済的効率とシステムの安定性を最大化するために必須の作業である. それを反映して,多くの開発者の時間が投資されてきた.

    クラスターのスケーリングはすべての開発者が何度も繰り返し行ってきた作業であり,いくつかの側面をテンプレート化し,共通化することができたならば開発のコストを大幅に削減できるだろう. それを実現するには,根本的なレベルからクラウドシステムの設計を考え直す必要がある. スケーリングを前提として考えることで,もっとシンプルで見通しがよいクラウドシステムの設計の仕組みはないだろうか? そのような動機が,サーバーレスアーキテクチャが誕生する背後にあった.

    従来の serverful なシステムでの最大の問題点は,サーバーをまるまる占有してしまうという点にある. すなわち, EC2 インスタンスを起動したとき,そのインスタンスは起動したユーザーだけが使えるものであり,計算のリソース (CPU や RAM) が独占的に割り当てられた状態になる. 固定した計算資源の割り当てがされてしまっているので,インスタンスの計算負荷が 0%であろうが 100%であろうが,均一の使用料金が起動時間に比例して発生する.

    サーバーレスアーキテクチャは,このような 独占的に割り当てられた計算リソースというものを完全に廃止することを出発点とする. サーバーレスアーキテクチャでは,計算のリソースは,クラウドプロバイダーがすべて管理する. クライアントは,仮想インスタンスを一台まるごと借りるのではなく,計算のタスクの需要が生まれる毎に,実行したいプログラム・コマンドをクラウドに提出する. クラウドプロバイダーは,自身のもつ巨大な計算リソースから空きを探し,提出されたプログラムを実行し,実行結果をクライアントに返す. 言い換えると,計算リソースのスケーリングやアロケーションなどはクラウドプロバイダーが一手に引き受け,ユーザーはジョブをサブミットすることに注力する,という枠組みである. これを図示すると, figure_title のようになる.

    従来のクラウドと Serverless クラウドの比較

    サーバーレスクラウドでは,スケーリングはすべてクラウドプロバイダーが引き受けるので,スケーラビリティーが保証されている. クライアントが同時に大量のタスクを送信した場合でも,クラウドプロバイダー側の独自の仕組みによってすべてのタスクが遅延なく実行される. また,サーバーレスクラウドを利用することで,クラウドのコストは実際に使用した計算の総量 (稼働時間) で決定されることになる. これは,計算の実行総量に関わらずインスタンスの起動時間で料金が決定されていた従来のシステムと比べて大きな違いである.

    サーバーレスクラウドは,従来のクラウドとは根本から異なったアプローチなので,コードの書き方やシステムの設計が大きく異なる. サーバーレスクラウドを開発・運用するには,サーバーレス固有の概念や用語に精通している必要がある. 以降では,実際にクラウドを動かしながら,サーバーレスをより具体的に体験していこう.

    従来型の(仮想インスタンスをたくさん起動するような)クラウドシステムは,賃貸と似ているかもしれない. 部屋を借りるというのは,その部屋でどれだけの時間を過ごそうが,月々の家賃は一定である. 同様に,仮想サーバーも,それがどれほどの計算を行っているかに関わらず,一定の料金が時間ごとに発生する.

    一方で,サーバーレスクラウドは,電気・水道・ガス料金 と似ている. こちらは,実際に使用した量に比例して料金が決定されている. サーバーレスクラウドも,実際に計算を行った総時間で料金が決まる仕組みになっている.

    サーバーレスクラウドを構成するコンポーネント

    サーバーレスアーキテクチャの概要がわかってきたところで,ここでは AWS においてサーバーレスクラウドを構成する様々なコンポーネントを紹介していこう. 特に, Lambda, S3, DynamoDB を取り上げ,解説する (figure_title). サーバーレスクラウドは,これらのコンポーネントを統合することで一つのシステムが出来上がる. ここでは, Lambda,S3,DynamoDB を利用する際に押さえておかなければならない知識を一通り説明しきる都合上,具体的なイメージがわきにくいかもしれない. が,続く Hands-on #5: サーバーレス入門 でそれぞれについてハンズオン形式で演習を行うので,そこでさらに理解を深めれば大丈夫である.

    Lambda, S3, DynamoDB のアイコン

    Lambda

    AWS でサーバーレスコンピューティングの中心を担うのが, Lambda である. Lambda の使い方を figure_title に図示している. Lambda の仕組みはシンプルで,まずユーザーは実行したいプログラムのコードを事前に登録しておく. プログラムは, Python, Node.js, Ruby などの主要な言語がサポートされている. Lambda に登録されたひとつひとつのプログラムを関数 (Function) とよぶ. そして,関数を実行したいときに,invoke コマンドを Lambda に送信する. Lambda では, invoke のリクエストを受け取るとただちに (数ミリセカンドから数百ミリセカンド程度の時間で) プログラムの実行を開始する. そして,実行結果をクライアントやその他の計算機に返す.

    AWS Lambda

    このように,Lambda では占有された仮想インスタンスは存在せず,実行を待っているプログラムだけがある状態である. invoke のリクエストに応じて,プログラムが AWS の巨大な計算機プールのどこかに配置され,実行される. 同時に複数のリクエストが来た場合でも, AWS はそれらを実行するための計算リソースを割り当て,並列的に処理を行ってくれる. 原理上は,数千から数万のリクエストが同時に来たとしても, Lambda はそれらを同時に実行することができる. このような,占有された仮想サーバーの存在なしに,動的に関数を実行するサービスのことを総称して FaaS (Function as a Service) とよぶ.

    Lambda ではそれぞれの関数につき, 128MB から 10240MB のメモリーを使用することができる (執筆時点の仕様). また,実効的な CPU のパワーはメモリーの量に比例する形で割り当てられる. すなわち,タスクに割り当てたメモリーの量が多ければ多いほど,より多くの CPU リソースが割り当てられることになる (しかし, RAM と CPU パワーの具体的な換算表は AWS からは公開されていない). 実行時間は 100 ミリ秒の単位で記録され,実行時間に比例して料金が決定される. table_title は Lambda の利用料金表である (執筆時点で ap-north-east1 リージョンを選択した場合).

    Lambda の料金表
    Memory (MB)Price per 100ms

    128

    $0.0000002083

    512

    $0.0000008333

    1024

    $0.0000016667

    3008

    $0.0000048958

    実行時間に比例する料金に追加して,リクエストを送信するごとに発生する料金が設定されている. これは,百万回のリクエストにつき $0.2 である. たとえば, 128MB のメモリーを使用する関数を,それぞれ 200 ミリ秒,合計で 100 万回実行した場合, 0.0000002083 * 2 * 10^6 + 0.2 = $0.6 の料金となる. ウェブサーバーのデータベースの更新など簡単な計算であれば,200 ミリ秒程度で実行できる関数も多いことから,100 万回データベースの更新を行ったとしても,たった $0.6 しかコストが発生しないことになる. また,コードが実行されず待機状態になっている場合は,発生する料金は 0 である. このように,実際に意味のある処理が行われた時間にのみ,料金が発生する仕組みになっている.

    Lambda は比較的短時間で完了する,反復性の高いタスクの実行に向いている. データベースの読み書きはその典型的な例であるが,そのほかにも,画像のサイズをトリミングしたり,サーバーサイドで定期的に実行されるメンテナンス処理などの利用が考えられる. また,複数の Lambda をリレー式に繋げることも可能で,シンプルな処理を組み合わせることで複雑なロジックを表現することができる.

    上述の Lambda の料金計算は,説明のためコストに寄与する要素をいくつか省いている点は承知いただきたい. 例えば, DynamoDB の読み書きに関する料金や,ネットワークの通信にかかわるコストが考慮されていない.

    サーバーレスストレージ: S3

    サーバーレスの概念は,ストレージにも拡張されている.

    従来的なストレージ (ファイルシステム) では,必ずホストとなるマシンと OS が存在しなければならない. したがって,それほどパワーは必要ないまでも,ある程度の CPU リソースを割かなければならない. また,従来的なファイルシステムでは,データ領域のサイズは最初にディスクを初期化するときに決めなければならず,後から容量を増加させることはしばしば困難である (ZFS などのファイルシステムを使えばある程度は自由にファイルシステムのサイズを変更することは可能である). よって,従来的なクラウドでは,ストレージを借りる際にはあらかじめディスクのサイズを指定せねばならず,ディスクの中身が空であろうと満杯であろうと,同じ利用料金が発生することになる (figure_title).

    Simple Storage Service (S3) は,サーバーレスなストレージシステムを提供する (figure_title). S3 は従来的なストレージシステムと異なり, OS に"マウントする”という概念はない. 基本的に API を通じてデータの読み書きの操作が行われる. また,データの冗長化や暗号化,バックアップの作成など,通常ならば OS と CPU が介在しなければならない操作も, API を通じて行うことができる. S3 では事前に決められたディスク領域のサイズはなく,データを入れれば入れた分だけ,保存領域は拡大していく (仕様上はペタバイトスケールのデータを保存することが可能である). ストレージにかかる料金は,保存してあるデータの総容量で決定される.

    S3 と従来的なファイルシステムの比較

    S3 を利用する際に,料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 説明のため主要な事項のみ取り出している. 詳細は 公式ドキュメンテーション "Amazon S3 pricing" を参照).

    S3 の利用料金
    項目料金

    Data storage (First 50TB)

    $0.023 per GB per month

    PUT, COPY, POST, LIST requests (per 1,000 requests)

    $0.005

    GET, SELECT, and all other requests (per 1,000 requests)

    $0.0004

    Data Transfer IN To Amazon S3 From Internet

    $0

    Data Transfer OUT From Amazon S3 To Internet

    $0.09 per GB

    第一に,データの保存には $0.025 per GB のコストが月ごとに発生する. したがって,1000GB のデータを S3 に一ヵ月保存した場合, $25 の料金が発生することになる. また,PUT, COPY, POST などのリクエスト (=データを書き込む操作) に対しては,データ容量に関係なく,1000 回ごとに $0.005 のコストが発生する. GET, SELECT などのリクエスト (=データを読み込む操作) に対しては,1000 回ごとに $0.0004 のコストが発生する. また, S3 はデータを外に取り出す際の通信にもコストが生じる. 執筆時点では,S3 からインターネットを通じて外部にデータを転送 (data-out) すると $0.09 per GB のコストが発生する. データをインターネットを通じて S3 に入れる (data-in) 通信は無料で行える. また, AWS の 同じ Region 内のサービス (Lambda や EC2 など) にデータを転送するのは無料である. AWS のリージョンをまたいだデータの転送にはコストが発生する. いずれにせよ,サーバーレスの概念に則り,すべての料金が従量課金制で決定される設定になっている.

    サーバーレスデータベース: DynamoDB

    サーバーレスの概念は,データベースにも適用することができる.

    ここでいうデータベースとは, Web サービスなどにおけるユーザーや商品の情報を記録しておくための保存領域のことを指している. 従来的に有名なデータベースとしては MySQL, PostgreSQL, MongoDB などが挙げられる. データベースと普通のストレージの違いは,データの検索機能にある. 普通のストレージではデータは単純にディスクに書き込まれるだけだが, データベースでは検索がより効率的になるようなデータの配置がされたり, 頻繁にアクセスされるデータはメモリーにキャッシュされるなどの機能が備わっている. これにより,巨大なデータの中から,興味のある要素を高速に取得することができる.

    このような検索機能を実現するには,当然 CPU の存在が必須である. したがって,従来的なデータベースを構築する際は,ストレージ領域に加えて,たくさんの CPU コアを搭載したマシンが用いられることが多い. また,データベースが巨大な場合は複数マシンにまたがった分散型のシステムが設計される. 分散型システムの場合は, Serverful クラウド (従来型) で議論したようにデータベースへのアクセス負荷に応じて適切なスケーリングがなされる必要がある.

    DynamoDB は, AWS が提供しているサーバーレスな分散型データベースである. サーバーレスであるので,占有されたデータベース用仮想インスタンスは存在せず, API を通じてデータの書き込み・読み出し・検索などの操作を行う. S3 と同様に,データ保存領域の上限は定められておらず,データを入れれば入れた分だけ,保存領域は拡大していく. また,データベースへの負荷が増減したときのスケーリングは, DynamoDB が自動で行うので,ユーザーは心配する必要はない.

    DynamoDB での利用料金の計算はやや複雑なのだが, "On-demand Capacity" というモードで使用した場合の料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 詳細は 公式ドキュメンテーション "Pricing for On-Demand Capacity" を参照).

    DynamoDB の利用料金
    項目料金

    Write request units

    $1.25 per million write request units

    Read request units

    $0.25 per million read request units

    Data storage

    $0.25 per GB-month

    DynamoDB ではデータの書き込み操作の単位を write request unit とよび,データの読み込み操作の単位を read request unit とよぶ. 基本的に, 1kB 以下のデータを一度書き込むと 1 write request unit を消費し,4kB 以下のデータを一度読み込むと 1 read request unit を消費する (詳しくは 公式ドキュメンテーション "Read/Write Capacity Mode" を参照のこと). write request units は 100 万回ごとに $1.25, read request units は 100 万回ごとに $0.25 のコストが設定されている. また,保存されたデータ容量に対して $0.25 per GB のコストが月ごとに発生する. DynamoDB は高速な検索機能などを備えたデータベースであるので, GB あたりのストレージコストは S3 に比べ 10 倍程度高い. DynamoDB のデータの転送に関わるコストは,同じリージョン内ならば data-in,data-out ともに $0 である. リージョンをまたいだ通信には別途コストが発生する.

    その他のサーバーレスクラウドの構成要素

    以上で紹介した Lambda, S3, DynamoDB がサーバーレスクラウドの中で最も使用する頻度が高いサービスになる. その他のサーバーレスクラウドの構成要素を以下に列挙する. いくつかについては,今後のハンズオンを行う中で改めて解説を行う.

    サーバーレスアーキテクチャは万能か?

    この問いへの答えは,筆者は NO であると考える.

    ここまで,サーバーレスの利点を強調して説明をしてきたが,まだまだ新しい技術なだけに,欠点,あるいはサーバーフルなシステムに劣る点は数多くある.

    大きな欠点を一つあげるとすれば,サーバーレスのシステムは各クラウドプラットフォームに固有なものなので,特定のプラットフォームでしか運用できないシステムになってしまう点であろう. AWS で作成したサーバーレスのシステムを, Google のクラウドに移植するには,かなり大掛かりなプログラムの書き換えが必要になる. 一方, serverful なシステムであれば,プラットフォーム間のマイグレーションは比較的簡単に行うことができる. クラウドプロバイダーとしては,自社のシステムへの依存度を強めることで,顧客を離さないようにするという狙いがあるのだろう…

    その他,サーバーレスコンピューティングの欠点や今後の課題などは,次の論文で詳しく議論されている. 興味のある読者はぜひ読んでいただきたい.

    Hands-on #5: サーバーレス入門

    前章ではサーバーレスアーキテクチャの概要の説明を行った. 本章では,ハンズオン形式でサーバーレスクラウドを実際に動かしながら,具体的な使用方法を学んでいこう. 今回のハンズオンでは Lambda, S3, DynamoDB の三つのサーバーレスクラウドの構成要素に触れていく. それぞれについて,短いチュートリアルを用意してある.

    Lambda ハンズオン

    まずは, Lambda を実際に動かしてみよう. ハンズオンのソースコードは GitHub の handson/serverless/lambda に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して Python で書かれたコードを Lambda に登録する. 続いて STEP 2 では, Invoke API を使用して,同時にいくつもの Lambda を起動し,並列な計算を行う. Lambda のワークフローを体験する目的で最小限の設定である.

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    py
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    -
    -class SimpleLambda(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    -
    -class SimpleLambda(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

    • 次に, Lambda に <1> で書いた関数を配置している. パラメータの意味は,文字どおりの意味なので難しくはないが,以下に解説する.

      • runtime=_lambda.Runtime.PYTHON_3_7: ここでは, Python3.7 を使って上記で定義された関数を実行せよ,と指定している. Python3.7 のほかに, Node.js, Java, Ruby, Go などの言語を指定することが可能である.

      • code=_lambda.Code.from_inline(FUNC): 実行されるべき関数が書かれたコードを指定する. ここでは, FUNC=... で定義した文字列を渡しているが,文字列以外にもファイルのパスを渡すことも可能である.

      • handler="index.handler": これは,コードの中にいくつかのサブ関数が含まれているときに,メインとサブを区別するためのパラメータである. handler という名前の関数をメイン関数として実行せよ,という意味である.

      • memory_size=128: メモリーは 128MB を最大で使用することを指定している.

      • timeout=core.Duration.seconds(10) タイムアウト時間を 10 秒に設定している. 10 秒以内に関数の実行が終了しなかった場合,エラーが返される.

      • dead_letter_queue_enabled=True: アドバンストな設定なので説明は省略する.

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    Lambda コンソール - 関数の一覧

    今回のアプリケーションで作成したのが SimpleLambda で始まるランダムな名前のついた関数だ. 関数の名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. 先ほどプログラムの中で定義した Python の関数がエディターから確認できる. さらに下の方にスクロールすると,関数の各種設定も確認できる.

    Lambda コンソール - 関数の詳細

    Lambda で実行されるコードは, Lambda のコンソール画面 (figure_title) のエディターで編集することもできる. デバッグをするときなどは,こちらを直接いじる方が早い場合もある. その場合は, CDK のコードに行った編集を反映させなおすことを忘れずに.

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    sh
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    ....................................................................................................
    -Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    figure_title で "Invocations" が関数が何度実行されたかを意味している. たしかに 100 回実行されていることがわかる. さらに, "Concurrent executions" は何個のタスクが同時に行われたかを示している. ここでは 96 となっていることから,96 個のタスクが並列的に実行されたことを意味している (これが 100 とならないのは,タスクの開始のコマンドが送られたのが完全には同タイミングではないことに起因する).

    このように,非常にシンプルではあるが, Lambda を使うことで,同時並列的に処理を実行することのできるクラウドシステムを簡単に作ることができた.

    もしこのようなことを従来的な serverful なクラウドで行おうとした場合,クラスターのスケーリングなど多くのコードを書くことに加えて,いろいろなパラメータを調節する必要がある.

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • partition_key: すべての DynamoDB テーブルには Partition key が定義されていなければならない. Partition key とは,テーブル内の要素 (レコード) ごとに存在する固有の ID のことである. 同一の Partition key をもった要素がテーブルの中に二つ以上存在することはできない (注: Sort Key を使用している場合は除く.詳しくは 公式ドキュメンテーション "Core Components of Amazon DynamoDB" 参照). また, Partition key が定義されていない要素はテーブルの中に存在することはできない. ここでは, Partition key に item_id という名前をつけている.

    • billing_mode: ddb.BillingMode.PAY_PER_REQUEST を指定することで, On-demand Capacity Mode の DynamoDB が作成される. ほかに PROVISIONED というモードがあるが,これはかなり高度なケースを除いて使用しないだろう.

    • removal_policy: CloudFormation のスタックが消去されたときに, DynamoDB も一緒に消去されるかどうかを指定する. このコードでは DESTROY を選んでいるので,すべて消去される. ほかのオプションを選択すると,スタックを消去しても DynamoDB のバックアップを残す,などの動作を定義することができる.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    DynamoDB のコンソール (テーブルの一覧)

    今回のアプリケーションで作成したのが SimpleDynamoDb で始まるランダムな名前のついたテーブルだ. テーブルの名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. "Items" のタブをクリックすると,テーブルの中のレコードを確認できる. 現時点ではなにもデータを書き込んでいないので,空である.

    DynamoDB のコンソール (テーブルの詳細画面)

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    python
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    -
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    -
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    python
    import boto3
    -ddb = boto3.resource('dynamodb')
    -
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    import boto3
    -ddb = boto3.resource('dynamodb')
    -
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    python
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if key is None:
    -        key = os.path.basename(filename)
    -
    -    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if key is None:
    -        key = os.path.basename(filename)
    -
    -    bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    python
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if filename is None:
    -        filename = os.path.basename(key)
    -
    -    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    -
    -    if filename is None:
    -        filename = os.path.basename(key)
    -
    -    bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #6: Bashoutter

    さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

    ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

    準備

    ハンズオンのソースコードは GitHub の handson/bashoutter に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. それ以外に必要な準備はない.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行できる.

    アプリケーションの説明

    API

    今回のアプリケーションでは,人々からの俳句の投稿を受け付けたり,投稿された俳句の一覧を取得する,といった機能を実装したい. この機能を実現するための最小限の設計として, table_title に示すような四つの REST API を今回は実装する. 俳句を投稿する,閲覧する,削除するという基本的なデータ操作を行うための API が完備されている. また, PATCH /haiku/{item_id} は, {item_id} で指定された俳句に”いいね”をするために使用する.

    Bashoutter API

    GET /haiku

    俳句の一覧を取得する

    POST /haiku

    新しい俳句を投稿する

    PATCH /haiku/{item_id}

    {item_id} で指定された俳句にお気に入り票を一つ入れる

    DELETE /haiku/{item_id}

    {item_id} で指定された俳句を削除する

    それぞれの API のパラメータおよび返り値の詳細は,ハンズオンのソースコードの中の swagger.yml に定義してある.

    Open API Specification (OAS; 少し前は Swagger Specification とよばれていた) は, REST API のための記述フォーマットである. OAS に従って API の仕様が記述されていると,簡単にドキュメンテーションを生成したり,クライアントアプリケーションを自動生成することができる. 今回用意した API 仕様 も, OAS に従って書いてある. 詳しくは Swagger の公式ドキュメンテーション などを参照.

    アプリケーションアーキテクチャ

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#5で作製するアプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントからの API リクエストは, API Gateway (後述)にまず送信され, API の URI で指定された Lambda 関数へ転送される.

    • それぞれの API のパス (リソース) ごとに独立した Lambda を用意する.

    • 俳句の情報 (作者,本文,投稿日時など) を記録するためのデータベース (DynamoDB) を用意する.

    • 各 Lambda 関数には, DynamoDB へのアクセス権を付与する.

    • 最後に,ウェブブラウザからコンテンツを表示できるよう, ウェブページの静的コンテンツを配信するための S3 バケットを用意する.クライアントはこの S3 バケットにアクセスすることで HTML/CSS/JS などのコンテンツを取得する.

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    python
    class Bashoutter(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    -
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    -
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    -
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    -
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    -
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    class Bashoutter(core.Stack):
    -
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    -
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    -
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    -
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    -
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    -
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    -
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    -
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

    • 静的コンテンツを配信するための S3 バケットを用意している.

    • それぞれの API で実行される Lambda 関数を定義している. 関数は Python3.7 で書かれており,コードは handson/bashoutter/api/api.py にある.

    • <3> で定義された Lambda 関数に対し,データベースへの読み書きのアクセス権限を付与している.

    • ここで,API Gateway により,各 API パスとそこで実行されるべき Lambda 関数を紐付けている.

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    python
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    今回のハンズオンでは説明の簡略化のため CloudFront の設定を行わなかったが,興味のある読者は次のリンクのプログラムが参考になるだろう.

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    python
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    python
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    -
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    -
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    -
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    -
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    python
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    そのような理由により,このコードでは GET のハンドラー関数に対しては grant_read_data() によって, read 権限のみを付与している.

    API Gateway

    API Gateway とは, API の"入り口"として,API のリクエストパスに従って Lambda や EC2 などに接続を行うという機能を担う (figure_title). Lambda や EC2 によって行われた処理の結果は,再び API Gateway を経由してクライアントに返される. このように,クライアントとバックエンドサーバーの間に立ち, API のリソースパスに応じて接続先を振り分けるようなサーバーをルーター,あるいはリバースプロキシとよんだりする. 従来的には,ルーターにはそれ専用の仮想サーバーが置かれることが一般的であった. しかし, API Gateway はサーバーレスなルーターとして,固定されたサーバーを配置することなく, API のリクエストが来たときのみ起動し,API のルーティングを実行する. サーバーレスであることの当然の帰結として,アクセスの件数が増大したときにはそれにルーティングの処理能力を自動で増やす機能も備わっている.

    API Gateway

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    python
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    -
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    -
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    -
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    -
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

    • 次に, api.root.add_resource() のメソッドを呼ぶことで, /haiku という API パスを追加している.

    • 続いて, add_method() を呼ぶことで, GET, POST のメソッドを /haiku のパスに定義している.

    • さらに, haiku.add_resource("{item_id}") により, /haiku/{item_id} という API パスを追加している.

    • 最後に, add_method() を呼ぶことにより, PATCH, DELETE のメソッドを /haiku/{item_id} のパスに定義している.

    このように, API Gateway の使い方は非常にシンプルで,逐次的に API パスとそこで実行されるメソッド・Lambda を記述していくだけでよい.

    このプログラムで 新規 API を作成すると, ランダムな URL がその API のエンドポイントとして割り当てられる. これを. api.example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    -
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    -
    -# デプロイを実行
    -$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    API Gateway コンソール画面 (1)

    今回デプロイした "BashoutterApi" という名前の API をクリックすることで figure_title のような画面に遷移し,詳細情報を閲覧できる. GET /haiku, POST /haiku などが定義されていることが確認できる.

    それぞれのメソッドをクリックすると,そのメソッドの詳細情報を確認できる. API Gateway は,前述したルーティングの機能だけでなく,認証機能などを追加することも可能である. このハンズオンではとくにこれらの機能は使用しないが, "Method Request" と書いてある項目などがそれに相当する. 次に, figure_title で画面右端の赤色で囲った部分に,この API で呼ばれる Lambda 関数が指定されていることに注目しよう. 関数名をクリックと,該当する Lambda のコンソールに遷移し,関数の中身を閲覧することが可能である.

    API Gateway コンソール画面 (2)

    次に, S3 のコンソール画面に移ってみよう. bashouter- で始まるランダムな名前のバケットが見つかるはずである (figure_title).

    S3 コンソール画面

    バケットの名前をクリックすることで,バケットの中身を確認してみよう. index.html のほか, css/, js/ などのディレクトリがあるのが確認できるだろう (figure_title). これらが,ウェブページの"枠"を定義している静的コンテンツである.

    S3 バケットの中身

    API リクエストを送信する

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"

    次のような出力が得られるだろう.

    sh
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    -
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    -
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている (figure_title 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    ウェブブラウザを開き,アドレスバーに S3 の URL を入力しへアクセスしてみよう. すると, figure_title のようなページが表示されるはずである.

    "Bashoutter" の GUI 画面

    ページが表示されたら,一番上の "API Endpoint URL" と書いてあるテキストボックスに,今回デプロイした API Gateway の URL を入力する (今回のアプリケーションでは,API Gateway の URL はランダムに割り当てられるのでこのような GUI の仕様になっている). そうしたら,画面の "REFRESH" と書いてあるボタンを押してみよう. データベースに俳句が登録済みであれば,俳句の一覧が表示されるはずである. 各俳句の左下にあるハートのアイコンをクリックすることで, "like" の票を入れることができる.

    新しい俳句を投稿するには,五七五と投稿者の名前を入力して, "POST" を押す. "POST" を押した後は,再び "REFRESH" ボタンを押すことで最新の俳句のリストをデータベースから取得する.

    アプリケーションの削除

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. Hands-on #5: サーバーレス入門 では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    これらの演習を通じて,世の中のウェブサービスがどのようにしてでき上がっているのか,少し理解が深まっただろうか? また,そのようなウェブアプリケーションを自分が作りたいと思ったとき,今回のハンズオンがその出発点となることができたならば幸いである.

    まとめ

    Appendix: 環境構築

    本書を読み進めるにあたって,ハンズオンのプログラムを実行するための環境を自分のローカルマシンにセットアップしなければならない. ここでは, AWS やコマンドラインの初心者を想定して,本章で必要なソフトウェアやライブラリのインストールなどを簡単に解説する. 以下に簡単な目次を示そう. 既に環境構築が済んでいる場合は適宜読み飛ばしていただき,関係のある箇所のみ目を通せば良い.

    使用する OS は Linux/Mac/Windows のどれを用いても構わない. Windows のユーザーは, Windows Subsytem for Linux (WSL) を使用することを想定している (WSL のインストール).

    また,本書のハンズオンを実行するための Docker イメージ を提供している. これを用いると, AWS CLI/CDK や Python の設定などをスキップできるので, Docker の使用方法を知っている読者には便利だろう.

    AWS アカウントの取得

    本書で提供するハンズオンを実際に自分で試すには,読者自身で AWS のアカウントの作成をする必要がある. 詳しいアカウントの作成の手順は 公式のドキュメンテーション に書かれているので,そちらも参照していただきたい. 以下の手順に従ってアカウントの作成を行う.

    まず,ウェブブラウザから AWS コンソール にアクセスし,右上の Create an AWS Account をクリックする (figure_title で実線で囲った部分).

    サインアップ (1): AWS コンソールにアクセス

    次に,遷移した先のページでメールアドレスとパスワードなどの登録を行う (figure_title).

    サインアップ (2): メールアドレス・パスワードなどの登録.

    続いて,住所や電話番号などを訊かれるので,すべて入力しよう (figure_title).

    サインアップ (3): 住所・電話番号の入力

    次に,クレジットカードの情報の登録を求められる (figure_title). 個人で AWS を利用する場合は,利用料金の請求はクレジットカードを経由して行われる. クレジットカードの登録なしには AWS を使い始めることはできないことに注意.

    サインアップ (4): クレジットカードの登録

    次の画面では,携帯電話の SMS またはボイスメッセージを利用した本人確認が求められる (figure_title). 希望の認証方法を選択し,自分の携帯電話番号を入力しよう.

    サインアップ (5): 携帯電話による本人確認

    無事に本人確認が完了すると,最後にサポートプランの選択を求められる (figure_title). 無料の Basic support を選択しておけば問題ない.

    サインアップ (6): サポートプランの選択

    以上のステップにより,アカウントの作成が完了する (figure_title). 早速ログインをして, AWS コンソールにアクセスできるか確認しておこう.

    サインアップ (7): アカウントの作成が完了した

    AWS のシークレットキーの作成

    AWS シークレットキーとは, AWS CLI や AWS CDK から AWS の API を操作するときに,ユーザー認証を行うための鍵のことである. AWS CLI/CDK を使うには,最初にシークレットキーを発行する必要がある. AWS シークレットキーの詳細は 公式ドキュメンテーション "Understanding and getting your AWS credentials" を参照.

    1. AWS コンソールにログインする.

    2. 画面右上のアカウント名をクリックし,表示されるプルダウンメニューから "My Security Credentials" を選択 (figure_title)

    3. "Access keys for CLI, SDK, & API access" の下にある "Create accesss key" のボタンをクリックする (figure_title)

    4. 表示された Access key ID, Secret access key を記録しておく (画面を閉じると二度と表示されない).

    5. 鍵を忘れてしまった場合などは,同じ手順で再発行が可能である.

    6. 発行したシークレットキーは, ~/.aws/credentials のファイルに書き込むか,環境変数に設定するなどして使う (詳しくは AWS CLI のインストール).

    AWS シークレットキーの発行1

    AWS シークレットキーの発行2

    AWS Educate Starter Account を用いている場合は,次の手順でシークレットキーを確認する.

    • AWS Educate のコンソール画面から, vocareum のコンソールに移動する (figure_title).

    • Account Details をクリックし,続いて AWS CLI: Show をクリックする.

    • aws_access_key_id, aws_secret_access_key, aws_session_token が表示される (figure_title). ここで表示された内容を ~/.aws/credentials にコピーする (AWS CLI のインストール 参照). aws_session_token の箇所も漏らさずコピーすること.

    • 続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

      [default] region = us-east-1 output = json

    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).

    vocareum コンソール

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    sh
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    -
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    -
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    本書のハンズオンではコマンドラインから AWS CLI のコマンドを実行したり, Python で書かれたプログラムを実行する. コマンドは基本的に UNIX のターミナルを想定して書かれている. Linux や Mac のユーザーは OS に標準搭載されているターミナルを用いれば良い. Windows を利用している読者は, Windows Subsystem for Linux (WSL) を利用することで,仮想の Linux 環境を構築することを推奨する. Cygwin などの Linux 環境をエミュレートするほかのツールでも構わないが,本書のプログラムは WSL でのみ動作確認を行っている.

    WSL とは, Windows の OS 上で Linux の仮想環境を起動するための, Microsoft 社が公式で提供しているソフトウェアである. Ubuntu など希望の Linux distribution が選択でき,基本的にすべての Linux 向けに作られたプログラム・ソフトウェアを使用することができる.

    執筆時点では WSL 2 が最新版として提供されているので,以下では WSL 2 のインストール手順を簡単に説明する. 細かな詳細などは, 公式ドキュメンテーション を参照のこと.

    前提として,使用される OS は Windows 10 (Pro または Home エディション) でなければならない. さらに,使用している Windows 10 のバージョンが WSL に対応するバージョンであるかを確認する. X64 のシステムでは Version 1903, Build 18362 以上でなければならない. バージョンが対応していない場合は、 Windows のアップデートを行う.

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    powersh
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    sh
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    Ubuntu 20.04 を初回に起動すると,初期設定が自動で開始され,数分待つことになる. 初期設定が終わると,ユーザー名・パスワードを設定するようプロンプトが出るので,プロンプトに従い入力する.

    これで WSL2 のインストールが完了した. 早速 WSL2 を起動してみよう. 左下の Windows メニューの検索バーに Ubuntu と入力すると, Ubuntu 20.04 のプログラムが見つかるはずである (figure_title). クリックして起動しよう.

    Ubuntu 20.04 の起動

    すると,ターミナルの黒い画面が立ち上がるだろう (figure_title). ls, top などのコマンドを打ってみて, WSL がきちんと動作していることを確認しよう.

    WSL の起動画面

    オプションとして, Windows Terminal というマイクロソフトから提供されているツールを使うと,より快適に WSL を使用することができる. 興味のある読者はこちらのインストールも推奨する.

    Docker のインストール

    Docker のインストールの方法は OS によって異なる.

    Mac ユーザーは, Docker Desktop をインストールする. インストールの方法は, Docker のウェブサイト から, Mac 版の Docker Desktop をダウンロードし,ダウンロードされたファイルをダブルクリックし, Applications のフォルダにドラッグするだけで良い. 詳細は 公式ドキュメンテーション を参照のこと.

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    ハンズオンを実行するために必要な, Node.js, Python, AWS CDK などがインストールされた Docker image を用意した. これを使用することで,自分のローカルマシンに諸々をインストールする必要なく,すぐにハンズオンのコードが実行できる.

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    sh
    root@aws-handson:~/programlisting
    root@aws-handson:~/programlisting

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい (プログラムを実行する など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    ライセンス

    本教科書およびハンズオンのソースコードは CC BY-NC-ND 4.0 に従うライセンスで公開しています.

    教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.

    - +
    Skip to content

    はじめに!

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:34.3k
    Reading:141 min

    本書の目的・内容

    本書は,東京大学計数工学科で 2021 年度 S1/S2 タームに開講されている"システム情報工学特論"の講義資料として作成された.

    本書の目的は,クラウドの初心者を対象とし,クラウドの基礎的な知識・概念を解説する. また, Amazon Web Services (以下, AWS) の提供するクラウド環境を実例として,具体的なクラウドの利用方法をハンズオンを通して学ぶ.

    とくに,科学・エンジニアリングの学生を対象として,研究などの目的でクラウドを利用するための実践的な手順を紹介する. 知識・理論の説明は最小限に留め,実践を行う中で必要な概念の解説を行う予定である. 読者が今後,研究などでクラウドを利用する際の,足がかりとなれば本書の目的は十分達成されたことになる.

    本書は以下のような三部構成になっている.

    本書の構成
    テーマハンズオン

    第一部 (1章-4章)

    クラウドの基礎

    • AWSに自分のサーバーを立ち上げる

    第二部 (5章-9章)

    クラウドを活用した機械学習

    • AWS と Jupyter を使って始めるディープラーニング

    • スケーラブルな自動質問回答ボットを作る

    • 並列化されたハイパーパラメータサーチの実装

    第三部 (10章-13章)

    サーバーレスアーキテクチャ入門

    • Lambda, DynamoDB, S3 の演習

    • 俳句を投稿する SNS "Bashoutter" を作る

    第一部は,クラウドの基礎となる概念・知識を解説する. セキュリティやネットワークなど,クラウドを利用する上で最低限おさえなければいけないポイントを説明する. ハンズオンでは,はじめての仮想サーバーを AWS に立ち上げる演習を行う.

    第二部では,クラウド上で科学計算 (とくに機械学習) を走らせるための入門となる知識・技術を解説する. あわせて, Docker とよばれる仮想計算環境の使用方法を紹介する. 一つ目のハンズオンでは, AWS のクラウドで Jupyter Notebook を起動し簡単な機械学習の計算を走らせる課題を実践する. 二つ目のハンズオンでは,深層学習を用いた自然言語処理により,質問に自動で回答を生成するボットを作成する. 最後に,複数台の GPU インスタンスからなるクラスターを起動し,並列に深層学習のハイパーパラメータサーチを行う方法を紹介する.

    第三部では,サーバーレスアーキテクチャとよばれる最新のクラウドのアーキテクチャを紹介する. これは,サーバーの処理能力を負荷に応じてより柔軟に拡大・縮小するための概念であり,それ以前 (Serverful としばしばよばれる) と質的に異なる設計思想をクラウドに導入するものである. ハンズオンでは,サーバーレスクラウドの主要なコンポーネントである Lambda, DynamoDB, S3 の演習を提供する. さらに,サーバーレスの技術を使用して簡単な SNS をクラウド上に作成する.

    これらの豊富なハンズオンにより, AWS 上にクラウドシステムを開発するための知識と技術が身につくはずである. いずれのハンズオンも,実用性を重視したものになっており,これらをベースにカスタマイズを施すことで様々な応用が可能である.

    本書のフィロソフィー

    本書のフィロソフィーを一言で表すなら, "ロケットで宇宙まで飛んでいって一度地球を眺めてみよう!" である.

    どういうことか?

    ここでいう"地球"とは,クラウドコンピューティングの全体像のことである. 言うまでもなく,クラウドという技術は非常に広範かつ複雑な概念で,幾多の情報技術・ハードウェア・アルゴリズムが精緻に組み合わさってできた総体である. そして,今日では科学研究から日常のインフラ設備に至るまで,我々の社会の多くの部分がクラウド技術によって支えられている.

    ここでいう"ロケット"とはこの講義のことである. この講義では,ロケットに乗って宇宙まで飛び立ち,地球(クラウド)の全体を自身の目で眺めてもらう. その際,ロケットの成り立ちや仕組み (背後にある要素技術やプログラムのソースコード) を深くは問わない. 将来,自分が研究などの目的でクラウドを利用することになった際に,改めて学んでもらえば良い. 本書の目的はむしろ,クラウドの最先端に実際に触れ,そこからどんな景色が見えるか(どんな応用が可能か)を実感してもらうことである.

    そのような理由で,本書はクラウドの基礎から応用まで幅広いテーマを取り扱う. 第一部はクラウドの基礎から始め,第二部では一気にレベルアップし機械学習(深層学習)をクラウドで実行する手法を解説する. さらに第三部では,サーバーレス・アーキテクチャというここ数年のうちに確立した全く新しいクラウドの設計について解説する. それぞれで本一冊分以上の内容に相当するものであるが,本書はあえてこれらを一冊にまとめ連続的に俯瞰するという野心的な意図をもって執筆された.

    決して楽な搭乗体験ではないかもしれないが,このロケットにしがみついてきてもらえれば,とてもエキサイティングな景色が見られることを約束したい.

    宇宙からみた地球 (Image from NASA https://www.nasa.gov/image-feature/planet-of-clouds)

    AWS アカウント

    本書では,ハンズオン形式で AWS のクラウドを実際に動かす演習を提供する. 自分でハンズオンを実行してみたい読者は,各自で AWS のアカウントの作成をしていただく. AWS のアカウントの作成の仕方は巻末付録 (AWS アカウントの取得) に簡単に記載したので,必要に応じて参照していただきたい.

    AWS にはいくつかの機能に対して無料利用枠が設定されており,いくつかのハンズオンは無料の範囲内で実行できる. 一方,ほかのハンズオン (とくに機械学習を扱うもの) では数ドル程度のコストが発生する. ハンズオンごとに発生するおおよそのコストについて記述があるので,注意をしながらハンズオンに取り組んでいただきたい.

    また,大学などの教育機関における講義で AWS を使用する際は, AWS Educate というプログラムを利用することも可能である. これは,講義の担当者が申請を行うことで,受講する学生に対し AWS クレジットが提供されるというプログラムである. AWS Educate を利用することで金銭的な負担なしに AWS を体験することができる. また,講義を経由せず個人でも AWS Educate に参加することも可能である. AWS Educate からは様々な学習教材が提供されているので,ぜひ活用してもらいたい.

    環境構築

    本書では, AWS 上にクラウドアプリケーションを展開するハンズオンを実施する. そこで紹介するプログラムを実行するためには,以下の計算機環境が必要である. インストールの方法については,巻末付録 (Appendix: 環境構築) に記してある. 必要に応じて参照し,環境構築を各自実施していただきたい.

    • UNIX 系コンソール: ハンズオンで紹介するコマンドを実行したり, SSH でサーバーにアクセスするため, UNIX 系のコンソール環境が必要である. Mac または Linux のユーザーは, OS に標準搭載のコンソール(ターミナルとも呼ばれる)を使用すればよい. Windows のユーザーは, Windows Subsystem for Linux (WSL) を使い, Linux の仮想環境のインストールを推奨する (WSL のインストール 参照).

    • Docker: 本書では Docker とよばれる仮想計算環境の利用方法を解説する. インストール手順については Docker のインストール を参照のこと.

    • Python: Version 3.6 以上をインストールする. とくに,ハンズオンでは venv モジュールを使用する. venv の使い方は Python クイックガイド 参照のこと.

    • Node.js: version 12.0 以上 をインストールする.

    • AWS CLI: Version 2 をインストールする. インストール手順については AWS CLI のインストール 参照のこと.

    • AWS CDK: Version 1.100 以上をインストールする. Version 2 以降には未対応である. インストール手順については AWS CDK のインストール 参照のこと.

    • AWS 認証鍵の設定: AWS API をコマンドラインから呼ぶには,認証鍵 (secret key) が設定されている必要がある. 認証鍵の設定については AWS CLI のインストール 参照のこと.

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は ハンズオン実行用の Docker image の使い方 に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    • Python の基本的な理解: 本書では Python を使ってプログラムの作成を行う. 使用するライブラリは十分抽象化されており,関数の名前を見ただけで意味が明瞭なものがほとんどであるので, Python に詳しくなくても心配する必要はない.

    • Linux コマンドラインの基礎的な理解: クラウドを利用する際,クラウド上に立ち上がるサーバーは基本的に Linux である. Linux のコマンドラインについて知識があると,トラブルシュートなどが容易になる. 筆者のおすすめの参考書は The Linux Command Line by William Shotts である. ウェブで無料で読むことができるので,読んだことのない人はぜひ一読を.

    講義に関連する資料

    ハンズオンで使うプログラムや教科書のソースコードは以下のウェブページで公開している.

    https://github.com/tomomano/learn-aws-by-coding

    本書で使用するノーテーションなど

    • コードやシェルのコマンドは monospace letter で記述する.

    • シェルに入力するコマンドは,それがシェルコマンドであると明示する目的で,先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力には $ はついていない点に留意する.

    また,以下のような形式で注意やチップスを提供する.

    追加のコメントなどを記す.

    発展的な議論やアイディアなどを紹介する.

    陥りやすいミスなどの注意事項を述べる.

    絶対に犯してはならないミスを指摘する.

    クラウド概論

    クラウドとは?

    Cloud

    クラウドとはなにか? クラウドという言葉は,それ自身がとても広い意味をもつので,厳密な定義付けを行うことは難しい.

    学術的な意味でのクラウドの定義づけをするとしたら,NIST(米国・国立標準技術研究所) による The NIST Definition of Cloud Computing が引用されることが多い. ここに記載されたクラウドの定義・モデルを図示したのが figure_title である.

    The NIST Definition of Cloud Computing

    これによると,クラウドとは以下の要件が満たされたハードウェア/ソフトウェアの総体のことをいう.

    • On-demand self-service 利用者のリクエストに応じて計算資源が自動的に割り当てられる.

    • Broad network access 利用者はネットワークを通じてクラウドにアクセスできる.

    • Resource pooling クラウドプロバイダーは,所有する計算資源を分割することで複数の利用者に計算資源を割り当てる.

    • Rapid elasticity 利用者のリクエストに応じて,迅速に計算資源の拡大あるいは縮小を行うことができる.

    • Measured service 計算資源の利用量を計測・監視することができる.

    …と,いわれても抽象的でよくわからないかもしれない.もう少し具体的な話をする.

    個人が所有する計算機で, CPU をアップグレードしようと思ったら,物理的に筐体を開け,CPU ソケットを露出させ,新しい CPU に交換する必要があるだろう. あるいは,ストレージがいっぱいになってしまったら,古いディスクを抜き取り,新しいディスクを挿入する必要がある. 計算機の場所を移動させたときには,新しい部屋の LAN ケーブルを差し込まないとネットワークには接続できない.

    クラウドでは,これらの操作がプログラムからのコマンドによって実行できる. CPU が 1000 個欲しいと思ったならば,そのようにクラウドプロバイダーにリクエストを送れば良い. すると,数分もしないうちに 1000 CPU の計算資源が割り当てられる. ストレージを 1TB から 10TB に拡張しようと思ったならば,そのようにコマンドを送ればよい (これは,Google Drive や Dropbox などのサービスなどで馴染みのある人も多いだろう). 計算資源を使い終わったら,そのことをプロバイダーに伝えれば,割り当て分はすぐさま削除される. クラウドプロバイダーは,使った計算資源の量を正確にモニタリングしており,その量をもとに利用料金の計算が行われる.

    このように,クラウドの本質は物理的なハードウェアの仮想化・抽象化であり,利用者はコマンドを通じて,まるでソフトウェアの一部かのように,物理的なハードウェアの管理・運用を行うことができる. もちろん,背後では,データセンターに置かれた膨大な数の計算機が大量の電力を消費しながら稼働している. クラウドプロバイダーはデータセンターの計算資源を上手にやりくりし,ソフトウェアとしてのインターフェースをユーザーに提供することで,このような仮想化・抽象化を達成しているわけである. クラウドプロバイダーの視点からすると,大勢のユーザーに計算機を貸し出し,データセンターの稼働率を常時 100%に近づけることで,利益率の最大化を図っているのである.

    著者の言葉で,クラウドの重要な特性を定義するならば,以下のようになる.

    クラウドとは計算機ハードウェアの抽象化である.つまり,物理的なハードウェアをソフトウェアの一部かのように自在に操作・拡大・接続することを可能にする技術である.

    先述の The NIST Definition of Cloud Computing に戻ると,クラウドプロバイダーによるクラウドサービスの形態としては,次の三つが定義されている (figure_title).

    • Software as a Service (SaaS): クラウド上で実行されるアプリケーションをサービスとして利用者に提供する形態. 例として, Google Drive や Slack などが挙げられる. 利用者は,背後にあるクラウドのインフラ (ネットワークやサーバーなど) には直接触れず,アプリケーションとして提供されているクラウドサービスを享受する.

    • Platform as a Service (PaaS): 顧客の作成したアプリケーション (多くの場合データベースと API リクエスト処理を行うサーバーのコードから構成される) をデプロイする環境をサービスとして利用者に提供する形態. PaaS では利用者はクラウドのインフラに直接触れることはなく,計算負荷が増減した際のサーバーのスケーリングはクラウドプロバイダーによってなされる. 例としては, Google App Engine や Heroku などがある.

    • Infrastructure as a Service (IaaS): クラウド上の計算インフラストラクチャーを従量課金制で利用者に提供する形態. 利用者は必要なネットワーク・サーバー・ストレージをプロバイダーから借り受け,そこに自身のアプリケーションを展開し運用する. IaaS の例としては AWS EC2 などが挙げられる.

    本書が扱うのは,主に IaaS におけるクラウド開発である. すなわち,開発者がクラウドのインフラを直接操作し,所望のネットワーク・サーバー・ストレージなどを一から構成し,そこにアプリケーションを展開するというクラウド開発である. この意味において,クラウドの開発とはクラウドインフラストラクチャーを定義・展開するプログラムを構築するステップインフラ上で実際に走るアプリケーションを作成するステップの二つに分けることができる. この二つは,プログラマーの技術としてはある程度分業を行うことが可能であるが,最も効率化・最適化されたクラウドシステムを構築するためには両方の理解が必須である. 本書では,前者 (クラウドインフラの記述) に重きを置きつつ,アプリケーションレイヤーの話題も取り扱う. PaaS とは,開発者はアプリケーションレイヤーの開発に注力し,クラウドインフラの部分はクラウドプロバイダーに依存するという概念である. PaaS は,クラウドインフラの開発が不要になることで開発の時間が短縮されるが,細かなインフラの挙動はコントロールできないという限界がある. 本書では PaaS についてはとくに取り扱わない.

    SaaS は本書の文脈では開発による"成果物"と捉えられるだろう. すなわち, IaaS を構成するプログラムを作成し展開することによって,一般の人が利用できるようなウェブ上の計算サービスやデータベースを提供することが開発の最終ゴールである. 本書のハンズオンではその実例として,シンプルな SNS の作成 (Hands-on #6: Bashoutter) などの演習を提供する.

    なお,最近では Function as a Service (FaaS) やサーバーレスコンピューティングなども新たなクラウドのカテゴリとして認知されている. これらの概念については Hands-on #5: サーバーレス入門 などの章で詳しく触れていく. 本書を読み進める中で明らかになるように,クラウドの技術は日進月歩である. 本書では実用的・教育的な観点から,従来的なクラウドの設計概念に触れたあと,サーバーレスなどの最新の技術も網羅するので,楽しみにしながら読み進めていただきたい.

    最後に,The NIST Definition of Cloud Computing によると,クラウドの運用形態について次のような定義がなされている (figure_title). 特定の組織・団体・企業の内部のみで使用されるクラウドを,プライベートクラウド (private cloud) とよぶ. 例えば,大学や研究機関では,その機関の構成員向けの大規模計算機サーバーが運用されていることが多い. プライベートクラウドは,組織の構成員ならば無料もしくは極めて割安のコストで計算を実行できる. しかし,使用できる計算資源の上限は限られる場合が多く,拡張時の柔軟性に欠ける場合もある.

    一方,商用のサービスとして一般の顧客に向けたクラウドのことを,パブリッククラウド (public cloud) とよぶ. 有名なパブリッククラウドプラットフォームの例を挙げると, Google 社が提供する Google Cloud Platform (GCP), Microsoft 社が提供する Azure, Amazon 社が提供する Amazon Web Services (AWS) などがある. パブリッククラウドを利用する場合は,プロバイダーの設定した利用料金を支払うことになる. その分,巨大なデータセンターを運用する企業の計算資源にアクセスすることができるので,計算のキャパシティは無尽蔵にあるといって過言でない.

    第三のクラウドの運用形態として,コミュニティクラウド (community cloud) が挙げられる. これは,例えば政府の省庁・機関など目的・役割を共有する団体・組織が共有して運用するクラウドを指す. 最後に,ハイブリッドクラウド (hybrid cloud) という形態もあり,これはプライベート・パブリック・コミュニティクラウドの二つ以上の組み合わせによって構成されるクラウドのことである. データ保護の観点から,いくつかの機密データやプライバシーに関わる情報はプライベートクラウドに保持し,残りのシステムをパブリッククラウドに依存する,などの形態が想定される.

    本書で説明するのは,基本的にパブリッククラウドを使ったクラウド開発である. 特に,Amazon Web Services (AWS) を使用して,具体的な技術と概念を学んでいく. 一方で,サーバーのスケーリングや仮想計算環境などのテクニックはすべてのクラウドに共通な概念であるので,クラウドのプラットフォームが変わろうと一般に通用する知識も同時に身につくはずだ.

    なぜクラウドを使うのか?

    上述のように,クラウドとはプログラムを通じて自由に計算資源を操作することのできる計算環境である. ここでは,リアルなローカル計算環境と比べて,なぜクラウドを使うと良いことがあるのかについて述べたい.

    1. 自由にサーバーのサイズをスケールできる

      なにか新しいプロジェクトを始めるとき,あらかじめ必要なサーバーのスペックを知るのは難しい. いきなり大きなサーバーを買うのはリスクが高い. 一方で,小さすぎるサーバーでは,後のアップグレードが面倒である. クラウドを利用すれば,プロジェクトを進めながら,必要な分だけの計算資源を確保することができる. 2. 自分でサーバーをメンテナンスする必要がない

      悲しいことに,コンピュータとは古くなるものである.最近の技術の進歩の速度からすると,5 年も経てば,もはや当時の最新コンピュータも化石と同じである. 5 年ごとにサーバーを入れ替えるのは相当な手間である. またサーバーの停電や故障など不意の障害への対応も必要である. クラウドでは,そのようなインフラの整備やメンテナンスはプロバイダーが自動でやってくれるので,ユーザーが心配する必要がない. 3. 初期コスト 0

      自前の計算環境とクラウドの,経済的なコストのイメージを示したのが figure_title である. クラウドを利用する場合の初期コストは基本的に 0 である. その後,使った利用量に応じてコストが増大していく. 一方,自前の計算環境では,大きな初期コストが生じる. その分,初期投資後のコストの増加は,電気利用料やサーバー維持費などに留まるため,クラウドを利用した場合よりも傾きは小さくなる. 自前の計算機では,ある一定期間後,サーバーのアップグレードなどによる支出が生じることがある. 一方,クラウドを利用する場合は,そのような非連続なコストの増大は基本的に生じない. クラウドのコストのカーブが,自前計算環境のコストのカーブの下にある範囲においては,クラウドを使うことは経済的なコスト削減につながる.

      クラウドと自前計算機環境の経済的コストの比較

    とくに,**1.**の点は研究の場面では重要であると筆者は感じる. 研究をやっていて,四六時中計算を走らせ続けるという場合は少ない. むしろ,新しいアルゴリズムが完成したとき・新しいデータが届いたとき,集中的・突発的に計算タスクが増大することが多いだろう. そういったときに,フレキシブルに計算力を増強させることができるのは,クラウドを使う大きなメリットである.

    ここまでクラウドを使うメリットを述べたが,逆に,デメリットというのも当然存在する.

    1. クラウドは賢く使わないといけない

      figure_title で示したコストのカーブにあるとおり,使い方によっては自前の計算環境のほうがコスト的に有利な場面は存在しうる. クラウドを利用する際は,使い終わった計算資源はすぐに削除するなど,利用者が賢く管理を行う必要があり,これを怠ると思いもしない額の請求が届く可能性がある. 2. セキュリティ

      クラウドは,インターネットを通じて世界のどこからでもアクセスできる状態にあり,セキュリティ管理を怠ると簡単にハッキングの対象となりうる. ハッキングを受けると,情報流出だけでなく,経済的な損失を被る可能性がある. 3. ラーニングカーブ

      上記のように,コスト・セキュリティなど,クラウドを利用する際に留意しなければならない点は多い. 賢くクラウドを使うには,十分なクラウドの理解が必要であり,そのラーニングカーブを乗り越える必要がある.

    Mac/Linux などでコマンドを入力するときに使用する,あの黒い画面のことを Terminal とよんだりする. この言葉の語源をご存知だろうか?

    Terminal

    この言葉の語源は,コンピュータが誕生して間もない頃の時代に遡る. その頃のコンピュータというと,何千何万のという数の真空管が接続された,会議室一個分くらいのサイズのマシンであった. そのような高価でメンテが大変な機材であるから,当然みんなでシェアして使うことが前提となる. ユーザーがコンピュータにアクセスするため,マシンからは何本かのケーブルが伸び,それぞれにキーボードとスクリーンが接続されていた… これを Terminal とよんでいたのである. 人々は,代わる代わる Terminal の前に座って,計算機との対話を行っていた.

    時代は流れ,Windows や Mac などのいわゆるパーソナルコンピュータの出現により,コンピュータはみんなで共有するものではなく,個人が所有するものになった.

    最近のクラウドの台頭は,みんなで大きなコンピュータをシェアするという,最初のコンピュータの使われ方に原点回帰していると捉えることもできる. 一方で,スマートフォンやウェアラブルなどのエッジデバイスの普及も盛んであり,個人が複数の"小さな"コンピュータを所有する,という流れも同時に進行しているのである.

    AWS 入門

    AWS とは?

    本書では,クラウドの実践を行うプラットフォームとして, AWS を用いる. 実践にあたって,最低限必要な AWS の知識を本章では解説しよう.

    AWS (Amazon Web Services) は Amazon 社が提供する総合的なクラウドプラットフォームである. AWS は Amazon 社が持つ膨大な計算リソースを貸し出すクラウドサービスとして,2006 年に誕生した. 2021 年では,クラウドプロバイダーとして最大のマーケットシェア (約 32%) を保持している (参照). Netflix や Slack をはじめとした多くのウェブ関連のサービスで,一部または全てのサーバーリソースが AWS から提供されているとのことである. よって,知らないうちに AWS の恩恵にあずかっている人も少なくないはずだ.

    最大のシェアをもつだけに,機能・サービスの幅広さはほかのクラウドプラットフォームと比べ抜きんでている. また,利用者数が多いことを反映して,公式あるいはサードパーティによる技術紹介記事が数多くウェブ上に存在しているだけでなく,ライブラリのユーザーコミュニティも大きく問題解決が捗るのも魅力の一つだ. 初期のころウェブビジネスを行う企業がユーザーの大半を占めていたが,最近は大学などでの科学研究用途としても頻繁に用いられるようになってきている.

    AWS の機能・サービス

    figure_title は,執筆時点において AWS で提供されている主要な機能・サービスの一覧である.

    AWSで提供されている主要なサービス一覧

    計算,ストレージ,データベース,ネットワーク,セキュリティなど,クラウドの構築に必要な様々な要素が独立したコンポーネントとして提供されている. 基本的に,これらを組み合わせることで一つのクラウドシステムができあがる.

    また,機械学習・音声認識・AR/VR など,特定のアプリケーションにパッケージ済みのサービスも提供されている. これらを合計すると全部で 170 個以上のサービスが提供されているとのことである (参照).

    AWS の初心者が陥りがちなのは,大量のサービスの数に圧倒され,どこから手をつけたらよいのかわからなくなる,という状況である. たくさんのサービスの中から,どのサービスをどの順番で学んでいったらいいのか,その道筋すら明らかでなく,大きな参入障壁となっていることは間違いない. だが実のところ, AWS の基本的な構成要素はそのうちの数個のみに限られる. 基本要素となる機能の使い方を知れば, AWS のおおよそのリソースを使いこなすことが可能になる. ほかの機能の多くは,基本の要素を組み合わせて特定のアプリケーションに特化したパッケージとして AWS が用意したものである. そのポイントを認知することが, AWS の学習の最初のステップである.

    ここでは, AWS 上でクラウドシステムを構築するときの基本となる構成要素を列挙する. これらは後のハンズオンで実際にプログラムを書きながら体験する. 現時点では,名前だけでも頭の片隅に記憶してもらえればよい.

    計算

    S3 EC2 (Elastic Compute Cloud) 様々なスペックの仮想マシンを作成し,計算を実行することができる. クラウドの最も基本となる構成要素である. Hands-on #1: 初めての EC2 インスタンスを起動する, Hands-on #2: AWS でディープラーニングを実践, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で詳しく触れる.

    S3 Lambda Function as a Service (FaaS) とよばれる,小さな計算をサーバーなしで実行するためのサービス. サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    ストレージ

    S3 EBS (Elastic Block Store) EC2 に付与することのできる仮想データドライブ. いわゆる"普通の"(一般的な OS で使われている)ファイルシステムを思い浮かべてくれたらよい.

    S3 S3 (Simple Storage Service) Object Storage とよばれる,API を使ってデータの読み書きを行う,いうなれば”クラウド・ネイティブ”なデータの格納システムである. サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    データベース

    S3 DynamoDB NoSQL 型のデータベースサービス (知っている人は mongoDB などを思い浮かべたらよい). サーバーレスアーキテクチャの章 (Serverless architecture) で詳しく解説する.

    ネットワーク

    S3 VPC(Virtual Private Cloud) AWS 上に仮想ネットワーク環境を作成し,仮想サーバー間の接続を定義したり,外部からのアクセスなどを管理する. EC2 は VPC の内部に配置されなければならない.

    API Gateway S3 API のエンドポイントとバックエンドのサービス (Lambda など) を接続する際に用いる,リバースプロキシとしての役割を担う. Hands-on #6: Bashoutter で詳しく解説する.

    Region と Availability Zone

    AWS を使用する際に知っておかなければならない重要な概念として, リージョン (Region)Availability Zone (AZ) がある (figure_title). 以下ではこの概念について簡単に記述する.

    AWSにおける Region と Availability Zones

    リージョン (Region) とは,おおまかに言うとデータセンターの所在地のことである. 執筆時点において, AWS は世界の 25 の国と地域でデータセンターを所有している. figure_title は執筆時点で利用できるリージョンの世界地図を示している. 日本では東京と大阪にデータセンターがある. 各リージョンには固有の ID がついており,例えば東京は ap-northeast-1, 米国オハイオ州は us-east-2,などと定義されている.

    Regions in AWS(出典: https://aws.amazon.com/about-aws/global-infrastructure/)

    AWS コンソールにログインすると,画面右上のメニューバーでリージョンを選択することができる(figure_title, 赤丸で囲った箇所). EC2, S3 などの AWS のリソースは,リージョンごとに完全に独立である. したがって,リソースを新たにデプロイする際,あるいはデプロイ済みのリソースを閲覧する際は,コンソールのリージョンが正しく設定されているか,確認する必要がある. ウェブビジネスを展開する場合などは,世界の各地にクラウドを展開する必要があるが,個人的な研究用途として用いる場合は,最寄りのリージョン (i.e. 東京) を使えば基本的に問題ない.

    AWSコンソールでリージョンを選択

    Avaialibity Zone (AZ) とは,リージョン内で地理的に隔離されたデータセンターのことである. それぞれのリージョンは 2 個以上の AZ を有しており,もし一つの AZ で火災や停電などが起きた場合でも,ほかの AZ がその障害をカバーすることができる. また, AZ 間は高速な AWS 専用ネットワーク回線で結ばれているため, AZ 間のデータ転送は極めて早い. AZ は,ビジネスなどでサーバーダウンが許容されない場合などに注意すべき概念であり,個人的な用途で使う限りにおいてはあまり深く考慮する必要はない.言葉の意味だけ知っておけば十分である.

    AWS を使用する際,どこのリージョンを指定するのがよいのだろうか? インターネットの接続速度の観点からは,地理的に一番近いリージョンを使用するのが一般的によいだろう. 一方, EC2 の利用料などはリージョンごとに価格設定が若干 (10-20%程度) 異なる. したがって,自分が最も頻繁に利用するサービスの価格が最も安く設定されているリージョンを選択する,というのも重要な視点である. また,いくつかのサービスは,特定のリージョンで利用できない場合もある. これらのポイントから総合的に判断して使用するリージョンを決めると良い.

    AWS Educate を利用している読者へ

    執筆時点において,AWS Educate による Starter Account を使用している場合は us-east-1 region のみ利用できる (参照).

    AWS でのクラウド開発

    AWS のクラウドの全体像がわかってきたところで,次のトピックとして,どのようにして AWS 上にクラウドの開発を行い,展開していくかについての概略を解説しよう.

    AWS のリソースを追加・編集・削除するなどの操作を実行するには,コンソールを用いる方法と,API を用いる方法の,二つの経路がある.

    コンソール画面からリソースを操作する

    AWS のアカウントにログインすると,まず最初に表示されるのがAWS コンソールである (figure_title).

    AWSマネージメントコンソール画面

    コンソールを使うことで, EC2 のインスタンスを立ち上げたり,S3 のデータを追加・削除したり,ログを閲覧したりなど,AWS 上のあらゆるリソースの操作を GUI (Graphical User Interface) を通して実行することができる. 初めて触る機能をポチポチと試したり,デバッグを行うときなどにとても便利である

    コンソールはさらっと機能を試したり,開発中のクラウドのデバッグをするときには便利なのであるが,実際にクラウドの開発をする場面でこれを直接いじることはあまりない. むしろ,次に紹介する API を使用して,プログラムとしてクラウドのリソースを記述することで開発を行うのが一般的である. そのような理由で,本書では AWS コンソールを使った AWS の使い方はあまり触れない. AWS のドキュメンテーションには,たくさんの チュートリアル が用意されており,コンソール画面から様々な操作を行う方法が記述されているので,興味がある読者はそちらを参照されたい.

    API からリソースを操作する

    API (Application Programming Interface) を使うことで,コマンドを AWS に送信し,クラウドのリソースの操作をすることができる. API とは,端的に言えば AWS が公開しているコマンドの一覧であり,GET, POST, DELETE などの REST API から構成されている (REST API については REST API で簡単に解説する). が,直接 REST API を入力するのは面倒であるので,その手間を解消するための様々なツールが提供されている.

    例えば, AWS CLI は, UNIX コンソールから AWS API を実行するための CLI (Command Line Interface) である. CLI に加えて,いろいろなプログラミング言語での SDK (Software Development Kit) が提供されている.以下に一例を挙げる.

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    python
    import boto3
    +
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    +
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン (Hands-on #1: 初めての EC2 インスタンスを起動する) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    python
    import boto3
    +
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)
    import boto3
    +
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    AWS CLI のインストールについては, AWS CLI のインストール を参照.

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは AWS CLI のインストール を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    sh
    $ aws s3 ls
    +
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    +
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    sh
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +
    +2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +
    +2020-06-07 23:54:19   13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    AWS 上のあらゆるリソースには, Amazon Resource Name (ARN) という固有の ID が付与されている. ARN は arn:aws:s3:::my_bucket/ のようなフォーマットで記述され,ARN を使用することで,特定の AWS リソース (S3 のバケットや EC2 のインスタンス) を一意的に参照することができる.

    S3 バケットや EC2 インスタンスなどには ARN に加えて,人間が読みやすい名前を定義することも可能である. この場合は,ARN または名前のどちらを用いても同じリソースを参照することが可能である.

    CloudFormation と AWS CDK

    CloudFormation による Infrastructure as Code (IaC)

    前節で述べたように,AWS API を使うことでクラウドのあらゆるリソースの作成・管理が可能である. よって,原理上は, API のコマンドを組み合わせていくことで,自分の作りたいクラウドを設計することができる.

    しかし,ここで実用上考慮しなければならない点が一つある. AWS API には大きく分けて,リソースを操作するコマンドと,タスクを実行するコマンドがあることである (figure_title).

    AWS APIはリソースを操作するコマンドとタスクを実行するコマンドに大きく分けられる.リソースを記述・管理するのに使われるのが, CloudFormation と CDK である.

    リソースを操作するとは,EC2 のインスタンスを起動したり,S3 のバケットを作成したり,データベースに新たなテーブルを追加する,などの静的なリソースを準備する 操作を指す. "ハコ"を作る操作とよんでも良いだろう. このようなコマンドは,クラウドのデプロイ時にのみ,一度だけ実行されればよい

    タスクを実行するコマンド とは, EC2 のインスタンスにジョブを投入したり, S3 のバケットにデータを読み書きするなどの操作を指す. これは, EC2 や S3 などのリソース ("ハコ") を前提として,その内部で実行されるべき計算を記述するものである. 前者に比べてこちらは動的な操作を担当する,と捉えることもできる.

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    json
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
    +
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
    +
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    python
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
    +
    +class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
    +
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
    +
    +class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
    +
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

    • AWS CDK Examples: CDK を使ったプロジェクトの例が多数紹介されている. ここにある例をテンプレートに自分のアプリケーションの開発を進めるとよい.

    Hands-on #1: 初めての EC2 インスタンスを起動する

    ハンズオンの第一回では, CDK を使って EC2 のインスタンス(仮想サーバー)を作成し,SSH でサーバーにログインする,という演習を行う. このハンズオンを終えれば,あなたは自分だけのサーバーを AWS 上に立ち上げ,自由に計算を走らせることができるようになるのである!

    準備

    ハンズオンのソースコードは GitHub の handson/ec2-get-started に置いてある.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行することができる.

    まずは,ハンズオンを実行するための環境を整える. これらの環境整備は,後のハンズオンでも前提となるものなので確実にミスなく行っていただきたい.

    • AWS Account: ハンズオンを実行するには個人の AWS アカウントが必要である. AWS アカウントの取得については AWS アカウントの取得 を参照のこと.
    • Python と Node.js: 本ハンズオンを実行するには,Python (3.6 以上),Node.js (12.0 以上) がインストールされていなければならない.
    • AWS CLI: AWS CLI のインストールについては, AWS CLI のインストール を参照. ここに記載されている認証鍵の設定も済ませておくこと.
    • AWS CDK: AWS CDK のインストールについては, AWS CDK のインストール を参照.
    • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    使用方法については ハンズオン実行用の Docker image の使い方 を参照のこと.

    SSH

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する (環境構築 を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    python
    class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class MyFirstEc2(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    • まず最初に,VPC を定義する.

    • 次に, security group (SG) を定義している. ここでは,任意の IPv4 のアドレスからの,ポート 22 (SSH の接続に使用される)への接続を許可している. それ以外の接続は拒絶される.

    • 最後に,上記で作った VPC と SG が付与された EC2 インスタンスを作成している. インスタンスタイプは t2.micro を選択し, Amazon Linux を OS として設定している.

    それぞれについて,もう少し詳しく説明しよう.

    VPC (Virtual Private Cloud)

    VPC のアイコン.

    VPC

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    python
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

    • cidr="10.10.0.0/23" : このパラメータは,VPC 内の IPv4 のレンジを指定している. CIDR 記法については, Wikipediaなどを参照. 10.10.0.0/2310.10.0.0 から 10.10.1.255 までの 512 個の連続したアドレス範囲を指している. つまり,この VPC では最大で 512 個のユニークな IPv4 アドレスが使えることになる. 今回はサーバーは一つなので 512 個は明らかに多すぎるが,VPC はアドレスの数はどれだけ作成しても無料なので,多めに作成した.

    • subnet_configuration=... : このパラメータは,VPC にどのようなサブネットを作るか,を決めている. サブネットの種類には private subnetpublic subnet の二種類がある. private subnet は基本的にインターネットとは遮断されたサブネット環境である. インターネットと繋がっていないので,セキュリティは極めて高く, VPC 内のサーバーとのみ通信を行えばよい EC2 インスタンスはここに配置する. Public subnet とはインターネットに繋がったサブネットである. 本ハンズオンで作成するサーバーは,外から SSH でログインを行いたいので, Public subnet 内に配置する. より詳細な記述は 公式ドキュメンテーション を参照.

    • natgateways=0 : これは少し高度な内容なので省略する (興味のある読者は 公式ドキュメンテーションを参照). が,これを 0 にしておかないと,NAT Gateway の利用料金が発生してしまうので,注意!

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    python
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    EC2 (Elastic Compute Cloud)

    EC2 のアイコン.

    EC2

    EC2 は AWS 上に仮想サーバーを立ち上げるサービスである. 個々の起動状態にある仮想サーバーのことをインスタンス (instance) とよぶ (しかし,口語的なコミュニケーションにおいては,サーバーとインスタンスという言葉は相互互換的に用いられることが多い).

    EC2 では用途に応じて様々なインスタンスタイプが提供されている. table_title に,代表的なインスタンスタイプの例を挙げる (執筆時点での情報). EC2 のインスタンスタイプのすべてのリストは 公式ドキュメンテーション "Amazon EC2 Instance Types" で見ることができる.

    EC2 instance types
    InstancevCPUMemory (GiB)Network bandwidth (Gbps)Price per hour ($)

    t2.micro

    1

    1

    -

    0.0116

    t2.small

    1

    2

    -

    0.023

    t2.medium

    2

    4

    -

    0.0464

    c5.24xlarge

    96

    192

    25

    4.08

    c5n.18xlarge

    72

    192

    100

    3.888

    x1e.16xlarge

    64

    1952

    10

    13.344

    table_title からわかるように, CPU は 1 コアから 96 コアまで,メモリーは 1GB から 2TB 以上まで,ネットワーク帯域は最大で 100Gbps まで,幅広く選択することができる. また,時間あたりの料金は,CPU・メモリーの占有数にほぼ比例する形で増加する. EC2 はサーバーの起動時間を秒単位で記録しており,利用料金は使用時間に比例する形で決定される. 例えば, t2.medium のインスタンスを 10 時間起動した場合,0.0464 * 10 = 0.464 ドルの料金が発生する.

    AWS には 無料利用枠 というものがあり, t2.micro であれば月に 750 時間までは無料で利用することができる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    python
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, Hands-on #2: AWS でディープラーニングを実践 でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    さて,ハンズオンのコードの理解ができたところで,プログラムを実際に実行してみよう.繰り返しになるが, 準備 での準備ができていることが前提である.

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    sh
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は Python クイックガイド に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    AWS のシークレットキーをセットする

    AWS CLI および AWS CDK を使うには, AWS のシークレットキーが設定されている必要がある. シークレットキーの発行については AWS のシークレットキーの作成 を参照のこと. シークレットキーを発行したら, AWS CLI のインストール を参照し,コマンドラインの設定を行う.

    手順をここに短く要約すると,一つ目の方法は AWS_ACCESS_KEY_ID などの環境変数を設定するやり方である. もう一つの方法は, ~/.aws/credentials に認証情報を保存しておく方式である. シークレットキーの設定は AWS CLI/CDK を使用するうえで共通のステップになるので,しっかりと理解しておくように.

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    sh
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    sh
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    おめでとう!これで,めでたく AWS 上に EC2 仮想サーバーを起動し,リモートからアクセスできるようになった!

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    sh
    $ cat /proc/cpuinfo
    +
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB
    $ cat /proc/cpuinfo
    +
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    sh
    $  top -n 1
    +
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
    +
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    +
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
    +
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    sh
    $ sudo yum update -y
    +$ sudo yum install -y python36
    $ sudo yum update -y
    +$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    sh
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    EC2 コンソール画面

    コンソール右上で,正しいリージョン (今回の場合は ap-northeast-1, Tokyo) が選択されているか,注意する!

    前章で CloudFormation について触れたが,今回デプロイしたアプリケーションも,CloudFormation のスタックとして管理されている. スタック (stack) とは, AWS リソースの集合のことを指す. 今回の場合は, VPC/EC2/SG などがスタックの中に含まれている. コンソールで CloudFormation のページに行ってみよう (figure_title).

    CloudFormation コンソール画面

    "MyFirstEc2" という名前のスタックがあることが確認できる. クリックをして中身を見てみると,EC2, VPC などのリソースがこのスタックに紐付いていることがわかる.

    スタックを削除

    これにて,第一回のハンズオンで説明すべき事柄はすべて完了した. 最後に,使わなくなったスタックを削除しよう. スタックの削除には,二つの方法がある.

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    ここまでが,本書の第一部の内容である. 盛りだくさんの内容であったが,ついてこれたであろうか?

    クラウド概論 では,クラウドの定義と用語の説明を行ったあと,なぜクラウドを使うのか,という点を議論した. 続いて AWS 入門 では,クラウドを学ぶ具体的なプラットフォームとして AWS を取り上げ, AWS を使用するにあたり最低限必要な知識と用語の説明を行った. さらに, Hands-on #1: 初めての EC2 インスタンスを起動する のハンズオンでは AWS CLI と AWS CDK を使って,自身のプライベートなサーバーを AWS 上に立ち上げる演習を行った.

    これらを通じて,いかに簡単に (たった数行のコマンドで!) 仮想サーバーを立ち上げたり,削除したりすることができるか,体験できただろう. 筆者は,クラウド概論 でクラウドの最も重要な側面はダイナミックに計算リソースを拡大・縮小できることである,と述べた. この言葉の意味が,ハンズオンを通じてより明らかになっただろうか? ここで学んだ技術を少し応用するだけで,自分のウェブページをホストする仮想サーバーを作成したり,大量のコアを搭載した EC2 インスタンスを用意して科学計算を実行するなど,いろいろなアプリケーションが実現できる.

    次章からは,今回学んだクラウドの技術を基に,より現実に即した問題を解くことを体験してもらう. お楽しみに!

    クラウドで行う科学計算・機械学習

    計算機が発達した現代では,計算機によるシミュレーションやビッグデータの解析は,科学・エンジニアリングの研究の主要な柱である. これらの大規模な計算を実行するには,クラウドは最適である. 本章から始まる第二部では,どのようにしてクラウド上で科学計算を実行するのかを,ハンズオンとともに体験してもらう. 科学計算の具体的な題材として,今回は機械学習(深層学習)を取り上げる.

    なお,本書では PyTorch ライブラリを使って深層学習のアルゴリズムを実装するが,深層学習および PyTorch の知識は不要である. 講義ではなぜ・どうやって深層学習をクラウドで実行するかに主眼を置いているので,実行するプログラムの詳細には立ち入らない. 将来,自分で深層学習を使う機会が来たときに,詳しく学んでもらいたい.

    なぜ機械学習をクラウドで行うのか?

    2010 年頃に始まった第三次 AI ブームのおかげで,学術研究だけでなく社会・ビジネスの文脈でも機械学習に高い関心が寄せられている. とくに,深層学習 (ディープラーニング) とよばれる多層のレイヤーからなるニューラルネットワークを用いたアルゴリズムは,画像認識や自然言語処理などの分野で圧倒的に高い性能を実現し,革命をもたらしている.

    深層学習の特徴は,なんといってもそのパラメータの多さである. 層が深くなるほど,層間のニューロンを結ぶ重みパラメータの数が増大していく. たとえば,最新の言語モデルである GPT-3 には1750 億個ものパラメータが含まれている. このような膨大なパラメータを有することで,深層学習は高い表現力と汎化性能を実現しているのである.

    GPT-3 に限らず,最近の SOTA (State-of-the-art) の性能を達成するニューラルネットワークでは,百万から億のオーダーのパラメータを内包することは頻繁になってきている. そのような巨大なニューラルネットを訓練 (最適化) させるのは,当然のことながら膨大な計算コストがかかる. 結果として,ひとつの計算機では丸一日以上の時間がかかる場合も珍しくない. 深層学習の発展の速度は目覚ましく,研究・ビジネス両方の観点からも,いかにスループットよくニューラルネットワークの最適化を行えるかが鍵となってくる. そのような問題を解決するのにとても有効な手段が,クラウドである! Hands-on #1: 初めての EC2 インスタンスを起動する でその片鱗を見たように,クラウドを使用することでゼロから数千に至るまでの数のインスタンスを動的に起動し,並列に計算を実行することができる. さらに,深層学習を加速させる目的で,深層学習の演算に専用設計された計算チップ (GPU など) がある. クラウドを利用すると,そのような専用計算チップも無尽蔵に利用することができる. 事実,先述した GPT-3 の学習も,詳細は明かされていないが,Microsoft 社のクラウドを使って行われたと報告されている.

    GPU による深層学習の高速化

    深層学習の計算で欠かすことのできない技術として, GPU (Graphics Processing Unit) について少し説明する.

    GPU は,その名のとおり,元々はコンピュータグラフィックスを出力するための専用計算チップである. CPU (Central Processing Unit) に対し,グラフィックスの演算に特化した設計がなされている. 身近なところでは, XBox や PS5 などのゲームコンソールなどに搭載されているし,ハイエンドなノート型・デスクトップ型計算機にも搭載されていることがある. コンピュータグラフィックスでは,スクリーンにアレイ状に並んだ数百万個の画素をビデオレート (30 fps) 以上で処理する必要がある. そのため,GPU はコアあたりの演算能力は比較的小さいかわりに,チップあたり数百から数千のコアを搭載しており (figure_title),スクリーンの画素を並列的に処理することで,リアルタイムでの描画を実現している.

    GPUのアーキテクチャ.GPUには数百から数千の独立した計算コアが搭載されている. (画像出典: https://devblogs.nvidia.com/nvidia-turing-architecture-in-depth/)

    このように,コンピュータグラフィクスの目的で生まれた GPU だが,2010 年前後から,その高い並列計算能力をグラフィックス以外の計算 (科学計算など) に用いるという流れ (General-purpose computing on GPU; GPGPU) が生まれた. GPU のコアは,その設計から,行列の計算など,単純かつ規則的な演算が得意であり,そのような演算に対しては数個程度のコアしかもたない CPU に比べて圧倒的に高い計算速度を実現することができる. 現在では GPGPU は分子動力学や気象シミュレーション,そして機械学習など多くの分野で使われている.

    ディープラーニングで最も頻繁に起こる演算が,ニューロンの出力を次の層のニューロンに伝える畳み込み (Convolution) 演算である (figure_title). 畳み込み演算は,まさに GPU が得意とする演算であり, CPU ではなく GPU を用いることで学習を飛躍的に (最大で数百倍程度) 加速させることができる.

    ニューラルネットワークにおける畳み込み演算.

    このように GPU は機械学習の計算で欠かせないものであるが,なかなか高価である. たとえば,科学計算・機械学習に専用設計された NVIDIA 社の Tesla V100 というチップは,一台で約百万円の価格が設定されている. 機械学習を始めるのに,いきなり百万円の投資はなかなか大きい. だが,クラウドを使えば,初期コスト0で GPU を使用することができる.

    機械学習を行うのに, V100 が必ずしも必要というわけではない. むしろ,研究者などでしばしば行われるのは,コンピュータゲームに使われるグラフィックス用の GPU を買ってきて (NVIDIA GeForce シリーズなど),開発のときはをそれを用いる,というアプローチである. グラフィックス用のいわゆる"コンシューマ GPU"は,市場の需要が大きいおかげで,10 万円前後の価格で購入することができる. V100 と比べると,コンシューマ GPU はコアの数が少なかったり,メモリーが小さかったりなどで劣る点があるが, それらを除いては計算能力にとくに制限があるわけではなく,開発の段階では十分な性能である場合がほとんどである. プログラムができあがって,ビッグデータの解析や,モデルをさらに大きくしたいときなどに,クラウドは有効だろう.

    クラウドで GPU を使うには, GPU が搭載された EC2 インスタンスタイプ (P3, P2, G3, G4 など) を選択しなければならない. table_title に,代表的な GPU 搭載のインスタンスタイプを挙げる (執筆時点での情報).

    GPUを搭載したEC2インスタンスタイプ
    InstanceGPUsGPU modelGPU Mem (GiB)vCPUMem (GiB)Price per hour ($)

    p3.2xlarge

    1

    NVIDIA V100

    16

    8

    61

    3.06

    p3n.16xlarge

    8

    NVIDIA V100

    128

    64

    488

    24.48

    p2.xlarge

    1

    NVIDIA K80

    12

    4

    61

    0.9

    g4dn.xlarge

    1

    NVIDIA T4

    16

    4

    16

    0.526

    table_title からわかるとおり, CPU のみのインスタンスと比べると少し高い価格設定になっている. また,古い世代の GPU (V100 に対しての K80) はより安価な価格で提供されている. 1 インスタンスあたりの GPU の搭載数は 1 台から最大で 8 台まで選択することが可能である.

    GPU を搭載した一番安いインスタンスタイプは, g4dn.xlarge であり,これには廉価かつ省エネルギー設計の NVIDIA T4 が搭載されている. 後のハンズオンでは,このインスタンスを使用して,ディープラーニングの計算を行ってみる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    V100 を一台搭載した p3.2xlarge の利用料金は一時間あたり $3.06 である. V100 が約百万円で売られていることを考えると,約 3000 時間 (= 124 日間),通算で計算を行った場合に,クラウドを使うよりも V100 を自分で買ったほうがお得になる,という計算になる (実際には,自前で V100 を用意する場合は, V100 だけでなく, CPU やネットワーク機器,電気使用料も必要なので,百万円よりもさらにコストがかかる).

    GPT-3 で使われた計算リソースの詳細は論文でも明かされていないのだが, Lambda 社のブログで興味深い考察が行われている (Lambda 社は機械学習に特化したクラウドサービスを提供している).

    記事によると,1750 億のパラメータを訓練するには,一台の GPU (NVIDIA V100) を用いた場合,342 年の月日と 460 万ドルのクラウド利用料が必要となる,とのことである. GPT-3 のチームは,複数の GPU に処理を分散することで現実的な時間のうちに訓練を完了させたのであろうが,このレベルのモデルになってくるとクラウド技術の限界を攻めないと達成できないことは確かである.

    深層学習を詳しく勉強したい人には以下の参考書を推薦したい. 深層学習の基礎的な概念や理論は普遍的であるが,この分野は日進月歩なので,常に最新の情報を取り入れることを忘れずに.

    Hands-on #2: AWS でディープラーニングを実践

    準備

    ハンズオン第二回では, GPU を搭載した EC2 インスタンスを起動し,深層学習モデルの学習と推論を実行する演習を行う.

    ハンズオンのソースコードは GitHub の handson/mnist に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. それ以外に必要な準備はない.

    初期状態の AWS アカウントでは, GPU 搭載の G タイプのインスタンスの起動上限が 0 になっていることがある. これを確認するには, AWS コンソールから EC2 の画面を開き,左のメニューから Limits を選択する. その中の Running On-Demand All G instances という数字が G インスタンスの起動上限を表している.

    もし,これが 0 になっていた場合は, AWS の自動申請フォームから上限緩和のリクエストを送る必要がある. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,東京 (ap-northeast-1) リージョンでは 0.71 $/hour のコストが発生する.

    AWS Educate Starter Account を使用している読者へ: 執筆時点においては, Starter Account には GPU 搭載型インスタンスを起動できないという制限が設けられている. したがって, Starter Account のユーザーはこのハンズオンを実行することはできない. 興味のある読者は,制限のない一般アカウントを自分自身で取得する必要があることに注意.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#2で作製するアプリケーションのアーキテクチャ

    図の多くの部分が,第一回ハンズオンで作成したアプリケーションと共通していることに気がつくだろう. 少しの変更で,簡単にディープラーニングを走らせる環境を構築することができるのである!主な変更点は次の3点である.

    • GPU を搭載した g4dn.xlarge インスタンスタイプを使用

    • ディープラーニングに使うプログラムがあらかじめインストールされた DLAMI (後述) を使用

    • SSH にポートフォワーディングのオプションつけてサーバーに接続し,サーバーで起動している Jupyter Notebook (後述) を使ってプログラムを書いたり実行したりする

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    python
    class Ec2ForDl(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class Ec2ForDl(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
    +
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
    +
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, クラウドで行う科学計算・機械学習 ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

    • ここでは,Deep Learning 用の諸々のソフトウェアがプリンストールされた AMI (Deep Learning Amazon Machine Image; DLAMI) を選択している (第一回では,Amazon Linux という AMI を使用していた). 使用する AMI の ID は リージョンごとに指定する必要があり,ここでは us-east-1ap-northeast-1 でそれぞれ定義している.

    DLAMI という新しい概念が出てきたので,説明しよう.

    AMI が us-east-1ap-northeast-1 でしか定義されていないので,提供されているコードはこの二つのリージョンのみでデプロイ可能である. もしほかのリージョンを利用したい場合は, AMI の ID を自身で検索し,コードに書き込む必要がある.

    DLAMI (Deep Learning Amazon Machine Image)

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    最も low-level なレイヤーとしては, GPU ドライバー がインストールされている. GPU ドライバーなしには OS は GPU とコマンドのやり取りをすることができない. 次のレイヤーが CUDAcuDNN である. CUDA は, NVIDIA 社が開発した, GPU 上で汎用コンピューティングを行うための言語であり, C++ 言語を拡張したシンタックスを備える. cuDNN は CUDA で書かれたディープラーニングのライブラリであり,n 次元の畳み込みなどの演算が実装されている. ここまでが, "Base" とよばれるタイプの DLAMI の中身である.

    これに加えて, "Conda" とよばれるタイプには, "Base" のプログラム基盤の上に, TensorFlowPyTorch などのライブラリがインストールされている. さらに, Anaconda による仮想環境を使うことによって, TensorFlow の環境・ PyTorch の環境・ MxNet の環境など,フレームワークを簡単に切り替えることができる (これについては,後のハンズオンで触れる). また, Jupyter Notebook もインストール済みである.

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    +
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    +
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    SSH ログインコマンドの <IP address> 部分は自身のインスタンスの IP アドレスを代入することを忘れずに.

    本書の提供している Docker を使ってデプロイを実行した人へ

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    Jupyter Notebook とは,インタラクティブに Python のプログラムを書いたり実行したりするためのツールである. Jupyter は GUI としてウェブブラウザを介してアクセスする形式をとっており,まるでノートを書くように,プロットやテーブルのデータも美しく表示することができる (figure_title). Python に慣れている読者は,きっと一度は使ったことがあるだろう.

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    sh
    $ cd ~ # go to home directory
    +$ jupyter notebook
    $ cd ~ # go to home directory
    +$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    Jupyter Notebook の使い方 (超簡易版)

    • Shift + Enter: セルを実行

    • Esc: Command mode に遷移

    • メニューバーの "+" ボタン または Command mode で A ⇒ セルを追加

    • メニューバーの "ハサミ" ボタン または Command mode で X ⇒ セルを削除

    ショートカットの一覧などは Ventsislav Yordanov 氏によるブログ が参考になる.

    PyTorch はじめの一歩

    PyTorch は Facebook AI Research LAB (FAIR) が中心となって開発を進めている,オープンソースのディープラーニングのライブラリである. PyTorch は 有名な例で言えば Tesla 社の自動運転プロジェクトなどで使用されており,執筆時点において最も人気の高いディープラーニングライブラリの一つである. 本ハンズオンでは, PyTorch を使ってディープラーニングの実践を行う.

    PyTorch の歴史のお話

    Facebook は PyTorch のほかに Caffe2 とよばれるディープラーニングのフレームワークを開発していた (初代 Caffe は UC Berkley の博士課程学生だった Yangqing Jia によって創られた). Caffe2 は 2018 年に PyTorch プロジェクトに合併された.

    また,2019 年 12 月,日本の Preferred Networks 社が開発していた Chainer も開発を終了し,PyTorch の開発チームと協業していくことが発表された (詳しくは プレスリリース を参照). PyTorch には,開発統合前から Chainer からインスパイアされた API がいくつもあり, Chainer の DNA は今も PyTorch に引き継がれているのである…!

    本格的なディープラーニングの計算に移る前に, PyTorch ライブラリを使って, GPU で計算を行うとはどういうものか,その入り口に触れてみよう.

    まずは,新しいノートブックを作成する. Jupyter のホーム画面の右上の "New" を押し,"conda_pytorch_p36" という環境を選択したうえで,新規ノートブックを作成する (figure_title). "conda_pytorch_p36" の仮想環境には, PyTorch がインストール済みである.

    新規ノートブックの作成. "conda_pytorch_p36" の環境を選択する.

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    python
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    python
    x = torch.rand(3,3)
    +print(x)
    x = torch.rand(3,3)
    +print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    python
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    python
    z = x + y
    +print(z)
    z = x + y
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    python
    z = z.to("cpu")
    +print(z)
    z = z.to("cpu")
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    完成した Jupyter Notebook は /handson/mnist/pytorch/pytorch_get_started.ipynb にある. Jupyter の画面右上の "Upload" からこのファイルをアップロードして,コードを走らせることが可能である.

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    python
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +
    +%time z = torch.matmul(x,y)
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +
    +%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    python
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
    +
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
    +
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    このベンチマークでは, dtype=torch.float32 と指定することで,32bit の浮動小数点型を用いている. ディープラーニングの学習および推論の計算には,32bit 型,場合によっては 16bit 型が使われるのが一般的である. これの主な理由として,教師データやミニバッチに起因するノイズが,浮動小数点の精度よりも大きいことがあげられる. 32bit/16bit を採用することで,メモリー消費を抑えたり,計算速度の向上が達成できる.

    上記のベンチマークから,GPU を用いることで,約 10 倍のスピードアップを実現することができた. スピードアップの性能は,演算の種類や行列のサイズに依存する. 行列積は,そのなかでも最も速度向上が見込まれる演算の一つである.

    実践ディープラーニング! MNIST 手書き数字認識タスク

    ここまで,AWS 上でディープラーニングの計算をするための概念や前提知識をながながと説明してきたが,ついにここからディープラーニングの計算を実際に走らせてみる.

    ここでは,機械学習のタスクで最も初歩的かつ有名な MNIST データセットを使った数字認識を扱う (figure_title). これは,0 から 9 までの手書きの数字の画像が与えられ,その数字が何の数字なのかを当てる,というシンプルなタスクである.

    MNIST 手書き数字データセット

    今回は, MNIST 文字認識タスクを,畳み込みニューラルネットワーク (Convolutional Neural Network; CNN) を使って解く. ソースコードは /handson/minist/pytorch/ にある mnist.ipynbsimple_mnist.py である. なお,このプログラムは, PyTorch の公式 Example Project 集 を参考に,多少の改変を行ったものである.

    まずは,カスタムのクラスや関数が定義された simple_mnist.py をアップロードしよう (figure_title). 画面右上の "Upload" ボタンをクリックし,ファイルを選択することでアップロードができる. この Python プログラムの中に,CNN のモデルや,学習の各イテレーションにおけるパラメータの更新などが記述されている. 今回はこの中身を説明することはしないが,興味のある読者は自身でソースコードを読んでみるとよい.

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    python
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
    +
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
    +
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    python
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
    +
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
    +
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    python
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
    +
    +print("Example data size:", example_data.shape)
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
    +
    +print("Example data size:", example_data.shape)
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    python
    model = Model()
    +model.to("cuda") # load to GPU
    model = Model()
    +model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    python
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    python
    model.eval()
    +
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    model.eval()
    +
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
    +
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は スタックを削除 参照).

    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    Docker 入門

    ここまでの章で扱ってきたハンズオンでは,単一のサーバーを立ち上げ,それに SSH でログインをして,コマンドを叩くことで計算を行ってきた. いわば,パーソナルコンピュータの延長のような形でクラウドを使ってきたわけである. このような,インターネットのどこからでもアクセスできるパーソナルコンピュータとしてのクラウドという使い方も,もちろん便利であるし,いろいろな応用の可能性がある. しかし,これだけではクラウドの本当の価値は十分に発揮されていないと言うべきだろう. クラウド概論 で述べたように,現代的なクラウドの一番の強みは自由に計算機の規模を拡大できることにある. すなわち,多数のサーバーを同時に起動し,複数のジョブを分散並列的に実行させることで大量のデータを処理してこそ,クラウドの本領が発揮されるのである.

    本章からはじまる 3 章分 (Docker 入門, Hands-on #3: AWS で自動質問回答ボットを走らせる, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) を使って,クラウドを利用することでどのように大規模な計算システムを構築しビッグデータの解析に立ち向かうのか,その片鱗をお見せしたい. とくに,前章で扱った深層学習をどのようにビッグデータに適用していくかという点に焦点を絞って議論していきたい. そのための前準備として,本章では Docker とよばれる計算機環境の仮想化ソフトウェアを紹介する (figure_title). 現代のクラウドは Docker なしには成り立たないといっても過言ではないだろう. クラウドに限らず,ローカルで行う計算処理にも Docker は大変便利である. AWS からは少し話が離れるが,しっかりと理解して前に進んでもらいたい.

    機械学習の大規模化

    先ほどから"計算システムの大規模化"と繰り返し唱えているが,それは具体的にはどのようなものを指しているのか? ここでは大規模データを処理するための計算機システムを,機械学習を例にとって見てみよう.

    クラウドで行う科学計算・機械学習 で紹介した GPT-3 のような,超巨大な数のパラメータを有する深層学習モデルを学習させたいとしよう. そのような計算を行いたい場合,一つのサーバーでは計算力が到底足りない. したがって,典型的には figure_title に示すような計算システムの設計がなされる. すなわち,大量の教師データを小さなチャンクとして複数のマシンに分散し,並列的にニューラルネットのパラメータを最適化していくという構造である.

    複数の計算機を使った大規模な深層学習モデルの訓練

    あるいは,学習済みのモデルを大量のデータに適用し,解析を行いたいとしよう. たとえば, SNS のプラットフォームで大量の画像が与えられて,それぞれの写真に何が写っているのかをラベルづけする,などのアプリケーションを想定できる. そのような場合は, figure_title のようなアーキテクチャが考えられるだろう. すなわち,大量のデータを複数のマシンで分割し,それぞれのマシンで推論の計算を行うというような構造である.

    複数の計算機による深層学習モデルを使った推論計算

    このような複数の計算機を同時に走らせるようなアプリケーションをクラウド上で実現するには,どのようにすればよいのだろうか?

    重要なポイントとして, figure_titlefigure_title で起動している複数のマシンは,基本的に全く同一の OS・計算環境を有している点である. ここで,個人のコンピュータで行うようなインストールの操作を,各マシンで行うこともできるが,それは大変な手間であるし,メンテナンスも面倒だろう. すなわち,大規模な計算システムを構築するには,簡単に計算環境を複製できるような仕組みが必要であるということがわかる.

    そのような目的を実現するために使われるのが, Docker とよばれるソフトウェアである.

    Docker とは

    Docker のアイコン

    Docker とは, コンテナ (Container) とよばれる仮想環境下で,ホスト OS とは独立した別の計算環境を走らせるためのソフトウェアである. Docker を使うことで, OS を含めたすべてのプログラムをコンパクトにパッケージングすることが可能になる (パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ). Docker を使うことで,クラウドのサーバー上に瞬時に計算環境を複製することが可能になり, figure_title で見たような複数の計算機を同時に走らせるためのシステムが実現できる.

    Docker は 2013 年に Solomon Hykes らを中心に開発され,それ以降爆発的に普及し,クラウドコンピューティングだけでなく,機械学習・科学計算の文脈などでも欠かすことのできないソフトウェアとなった. Docker はエンタープライズ向けの製品を除き無料で使用することができ,コアの部分は オープンソースプロジェクト として公開されている. Docker は Linux, Windows, Mac いずれの OS でも提供されている. 概念としては, Docker は仮想マシン (Virtual machine; VM) にとても近い. ここでは, VM との対比をしながら,Docker とはなにかを簡単に説明しよう.

    仮想マシン (VM) とは,ホストとなるマシンの上に,仮想化された OS を走らせる技術である (figure_title). VM には ハイパーバイザー (Hypervisor) とよばれるレイヤーが存在する. Hypervisor はまず,物理的な計算機リソース (CPU, RAM, network など) を分割し,仮想化する. たとえば, ホストマシンに物理的な CPU が 4 コアあるとして,ハイパーバイザーはそれを (2,2) 個の組に仮想的に分割することができる. VM 上で起動する OS には,ハイパーバイザーによって仮想化されたハードウェアが割り当てられる. VM 上で起動する OS は基本的に完全に独立であり,たとえば OS-A は OS-B に割り当てられた CPU やメモリー領域にアクセスすることはできない (これを isolation とよぶ). VM を作成するための有名なソフトウェアとしては, VMwareVirtualBoxXen などがある. また,これまで触ってきた EC2 も,基本的に VM 技術を使うことで所望のスペックをもった仮想マシンがユーザーに提示される.

    Docker も, VM と同様に,仮想化された OS をホストの OS 上に走らせるための技術である. VM に対し, Docker ではハードウェアレベルの仮想化は行われておらず,すべての仮想化はソフトウェアレベルで実現されている (figure_title). Docker で走る仮想 OS は,多くの部分をホストの OS に依存しており,結果として非常にコンパクトである. その結果, Docker で仮想 OS を起動するために要する時間は, VM に比べて圧倒的に早い. また, パッケージ化された環境 (=イメージ) のサイズも完全な OS に比べ圧倒的に小さくなるので,ネットワークを通じたやり取りが非常に高速化される点も重要である 加えて, VM のいくつかの実装では,メタル (仮想化マシンに対して,物理的なハードウェア上で直接起動する場合のこと) と比べ,ハイパーバイザーレイヤーでのオーバーヘッドなどにより性能が低下することが知られているが, Docker ではメタルとほぼ同様の性能を引き出すことができるとされている.

    その他, VM との相違点などはたくさんあるのだが,ここではこれ以上詳細には立ち入らない. 大事なのは, Docker とはとてもコンパクトかつハイパフォーマンスな仮想計算環境を作るツールである,という点である. その手軽さゆえに,2013 年の登場以降,クラウドシステムでの利用が急速に増加し,現代のクラウドでは欠くことのできない中心的な技術になっている.

    Docker (左) と VM (右) の比較 (画像出典: https://www.docker.com/blog/containers-replacing-virtual-machines/)

    職業的プログラマーにとっての"三種の神器"とはなんだろうか? 多様な意見があると思うが,筆者は Git, Vim そして Docker を挙げたい.

    Git は多くの読者がご存じの通り,コードの変更を追跡するためのシステムである. Linux の作成者である Linus Torvalds によって 2005 年に誕生した. チームでの開発を進める際には欠かせないツールだ.

    Vim は 1991 年から 30 年以上の間プログラマーたちに愛されてきたテキストエディターである. Stackoverflow が行った 2019 年のアンケート によると,開発環境の部門で 5 位の人気を獲得している. たくさんのショートカットと様々なカスタム設定が提供されているので,初見の人にはなかなかハードルが高いが,一度マスターすれば他のモダンなエディターや統合開発環境に負けない,あるいはそれ以上の開発体験を実現することができる.

    これらの十年以上の歴史あるツールに並んで,第三番目の三種の神器として挙げたいのが Docker だ. Docker はプログラマーの開発のワークフローを一変させた. たとえば,プロジェクトごとに Docker イメージを作成することで,どの OS・コンピュータ でも全く同じ計算環境で開発・テストを実行することができるようになった. また, DevOpsCI / CD (Continuous Integration / Continuous Deployment) といった最近の開発ワークフローも Docker のようなコンテナ技術の存在に立脚している. さらにはサーバーレスコンピューティング (Serverless architecture) といった概念も,コンテナ技術の生んだ大きな技術革新といえる.

    あなたにとっての三種の神器はなんだろうか? また,これからの未来ではどんな新しいツールが三種の神器としてプログラマーのワークフローを革新していくだろうか?

    Docker チュートリアル

    Docker とはなにかを理解するためには,実際に触って動かしてみるのが一番有効な手立てである. ここでは, Docker の簡単なチュートリアルを行っていく.

    Docker のインストールについては, Docker のインストール および 公式のドキュメンテーション を参照してもらいたい. Docker のインストールが完了している前提で,以下は話を進めるものとする.

    Docker 用語集

    Docker を使い始めるに当たり,最初に主要な用語を解説しよう. 次のパラグラフで太字で強調された用語を頭に入れた上で,続くチュートリアルに取り組んでいただきたい.

    Docker を起動する際の大まかなステップを示したのが figure_title である. パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ. イメージは, Docker Hub などのリポジトリで配布されているものをダウンロードするか,自分でカスタムのイメージを作成することも可能である. イメージを作成するための”レシピ”を記述したファイルが Dockerfile である. Dockerfile からイメージを作成する操作を build とよぶ. イメージがホストマシンのメモリにロードされ,起動状態にある計算環境のことを コンテナ (Container) とよぶ. Container を起動するために使用されるコマンドが run である.

    Image と Container

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, Hands-on #2: AWS でディープラーニングを実践 でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    sh
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    python
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
    +
    +RUN apt-get update \
    +    && apt-get install nano
    +
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
    +
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
    +
    +#
    +RUN npm install -g aws-cdk@1.100
    +
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
    +
    +# copy hands-on source code in /root/
    +COPY handson/ /root/handson
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
    +
    +RUN apt-get update \
    +    && apt-get install nano
    +
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
    +
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
    +
    +#
    +RUN npm install -g aws-cdk@1.100
    +
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
    +
    +# copy hands-on source code in /root/
    +COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    Singularity は科学計算や HPC (High Performance Computing) の分野で人気の高いコンテナプラットフォームである. Singularity では大学・研究機関の HPC クラスターでの運用に適したような設計が施されている. たとえば, Docker は基本的には root 権限で実行されるのに対し, Singularity はユーザー権限 (コマンドを実行したユーザー自身) でプログラムが実行される. root 権限での実行は Web サーバーのように個人・企業がある特定のサービスのために運用するサーバーでは問題ないが,多数のユーザーが多様な目的で計算を実行する HPC クラスターでは問題となる. また,Singularity は独自のイメージの作成方法・エコシステムをもっているが, Docker イメージを Singularity のイメージに変換し実行する機能も有している.

    podman は Red Hat 社によって開発されたもう一つのコンテナプラットフォームである. podman は基本的に Docker と同一のコマンドを採用しているが,実装は Red Hat によってスクラッチから行われた. podman では, Singularity と同様にユーザー権限でのプログラムの実行を可能であり,クラウドおよび HPC の両方の環境に対応するコンテナプラットフォームを目指して作られた. また,その名前にあるとおり pod とよばれる独自の概念が導入されている.

    著者の個人的な意見としては,現時点では Docker をマスターしておけば当面は困ることはないと考えるが,興味のある読者はぜひこれらのツールも試してみてはいかがだろうか?

    Elastic Container Service (ECS)

    ECS のアイコン

    ここまでに説明してきたように, Docker を使うことで仮想計算環境を簡単に複製・起動することが可能になる. 本章の最後の話題として, AWS 上で Docker を使った計算システムを構築する方法を解説しよう.

    Elastic Container Service (ECS) とは, Docker を使った計算機クラスターを AWS 上に作成するためのツールである (figure_title). ECS を使用することで, Docker にパッケージされたアプリケーションを計算機クラスターに投入したり,計算機クラスターのインスタンスを追加・削除する操作 (=スケーリング) を行うことができる.

    ECS の概要を示したのが figure_title である. ECS は,タスク (Task) と呼ばれる単位で管理された計算ジョブを受け付ける. システムにタスクが投入されると,ECS は最初にタスクで指定された Docker イメージを外部レジストリからダウンロードしてくる. 外部レジストリとしては, Docker Hub や AWS 独自の Docker レジストリである ECR (Elastic Container Registry) を指定することができる.

    ECS の次の重要な役割はタスクの配置である. あらかじめ定義されたクラスター内で,計算負荷が小さい仮想インスタンスを選び出し,そこに Docker イメージを配置することで指定された計算タスクが開始される. "計算負荷が小さい仮想インスタンスを選び出す" と言ったが,具体的にどのような戦略・ポリシーでこの選択を行うかは,ユーザーの指定したパラメータに従う.

    また,クラスターのスケーリングも ECS における重要な概念である. スケーリングとは,クラスター内のインスタンスの計算負荷をモニタリングし,計算負荷に応じてインスタンスの起動・停止を行う操作を指す. クラスター全体の計算負荷が指定された閾値 (たとえば 80%の稼働率) を超えていた場合,新たな仮想インスタンスをクラスター内に立ち上げる操作を scale-out (スケールアウト) とよび, 負荷が減った場合に不要なインスタンスを停止する操作を scale-in (スケールイン) とよぶ. クラスターのスケーリングは, ECS がほかの AWS のサービスと連携することで実現される. 具体的には, EC2 の Auto scaling group (ASG)Fargate の2つの選択肢が多くの場合選択される. ASG については Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する, Fargate については Hands-on #3: AWS で自動質問回答ボットを走らせる でより詳細に解説する.

    これら一連のタスクの管理を, ECS は自動でやってくれる. クラスターのスケーリングやタスクの配置に関してのパラメータを一度指定してしまえば,ユーザーは (ほとんどなにも考えずに) 大量のタスクを投入することができる. クラスターのスケーリングによってタスクの量にちょうど十分なだけのインスタンスが起動し,タスクが完了した後は不要なインスタンスはすべて停止される.

    さて,ここまで説明的な話が続いてしまったが,次章からは早速 Docker と AWS を使って大規模な並列計算システムを構築していこう!

    ECS の概要

    Hands-on #3: AWS で自動質問回答ボットを走らせる

    ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.

    通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 (Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.

    Fargate

    ハンズオンに入っていく前に, Fargate という AWS の機能を知っておく必要がある (figure_title).

    Fargate のアイコン

    ECS の概要を示した figure_title をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. EC2 あるいは Fargate のいずれかである. EC2 を用いた場合は,先の章 (Hands-on #1: 初めての EC2 インスタンスを起動する, Hands-on #2: AWS でディープラーニングを実践) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 (Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する) で説明することにする.

    Fargate とは, ECS での利用に特化して設計された,コンテナを使用した計算タスクを走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は docker run のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.

    Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは 公式ドキュメンテーション "Amazon ECS on AWS Fargate" 参照). クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.

    以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.

    厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.

    準備

    ハンズオンのソースコードは GitHub の handson/qa-bot にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    sh
    answer: 1921
    answer: 1921

    人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

    今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    sh
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    sh
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    出力:

    sh
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    今回提供する Q-A ボットの Docker のソースコードは https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile にある.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,以下のような設計である.

    • クライアントは,質問を AWS 上のアプリケーションに送信する.

    • 質問のタスクは ECS によって処理される.

    • ECS は, Docker Hub から,イメージをダウンロードする.

    • 次に,ECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.

      • このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.
    • ジョブが実行される.

    • ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.

    • 最後に,クライアントは DynamoDB から質問への回答を読み取る.

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    sh
    class EcsClusterQaBot(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
    +
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
    +
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
    +
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
    +
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    class EcsClusterQaBot(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
    +
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
    +
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
    +
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
    +
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

    • ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.

    • ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.

    • ここで,実行するタスクを定義している (task definition).

    • ここで, タスクの実行で使用する Docker イメージを定義している.

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    sh
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
    +
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
    +
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
    +
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
    +
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.

    このコードで cpu=1024 と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は 公式ドキュメンテーション "Amazon ECS on AWS Fargate" を参照のこと.

    CPU ユニットと 指定可能なメモリー量の換算表

    CPU ユニット

    メモリーの値

    256 (.25 vCPU)

    0.5 GB, 1 GB, 2 GB

    512 (.5 vCPU)

    1 GB, 2 GB, 3 GB, 4 GB

    1024 (1 vCPU)

    2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB

    2048 (2 vCPU)

    Between 4 GB and 16 GB in 1-GB increments

    4096 (4 vCPU)

    Between 8 GB and 30 GB in 1-GB increments

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. figure_title で, FARGATE という文字の下に 0 Running tasks, 0 Pending tasks と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.

    ECS コンソール画面

    続いて,この画面の左のメニューバーから Task Definitions という項目を見つけ,クリックしよう. 移動した先のページで EcsClusterQaBotEcsClusterQaBotTaskDefXXXX という項目が見つかるので,開く. 開いた先のページをスクロールすると figure_title に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.

    Task definition の確認

    タスクの実行

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, "Tasks" という名前のタブがあるので,それを開く (figure_title). すると,実行中のタスクの一覧が表示されるだろう.

    ECS のタスクの実行状況をモニタリング

    figure_title で見て取れるように, "Last status = Pending" となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.

    しばらく待つうちに, Status が "RUNNING" に遷移し,計算が始まる. 計算が終わると, Status は "STOPPED" に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.

    figure_title の画面から, "Task" の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (figure_title). "Last status", "Platform version" など,タスクの情報が表示されている. また, "Logs" のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.

    質問タスクの実行結果

    さて, run_task.py を実行したコマンドラインに戻ってきてみると, figure_title のような出力が得られているはずである. "Momotaro" という正しい回答が返ってきている!

    質問タスクの実行結果

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する

    ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

    本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

    Auto scaling groups (ASG)

    ハンズオンに入っていく前に, Auto scaling groups (ASG) とよばれる EC2 の概念を知っておく必要がある.

    ECS の概要を示した figure_title を振り返って見てほしい. 前章 (Hands-on #3: AWS で自動質問回答ボットを走らせる) でも説明したが, ECS のクラスターで計算を担う実体としては EC2 と Fargate を指定することができる. Fargate については前章で記述した. Fargate を用いると,自在にスケールする計算環境をとても簡単な設定で構築することができた. しかし, GPU を利用することができないなど,いくつかの制約があった. EC2 を使用した計算環境を指定することで,プログラミングの複雑度は増すが, GPU やその他のより高度かつ複雑な設定を伴ったクラスターを構築することができる.

    EC2 クラスターには ASG と呼ばれるサービスが配置される. ASG は複数の EC2 インスタンスをロジカルな単位でグループ化することでクラスターを構成する. ASG はクラスター内に新しいインスタンスを起動する,あるいは不要になったインスタンスを停止するなどのスケーリングを担う. ASG で重要な概念として, desired capacity, minimum capacity, maximum capacity というパラメータがある. minimum capacity, maximum capacity は,それぞれクラスター内に配置できるインスタンスの数の最小値・最大値を指定するパラメータである. 前者は,クラスターに負荷がかかっていない場合でもアイドリング状態にあるインスタンスを維持することで,急に負荷が増大した時などのバッファーとして作用することができる. 後者は,負荷が急に増えたときに,過剰な数のインスタンスが起動する事態を防ぎ,経済的なコストの上限を定める役割を果たす.

    desired capacity が,その時々でシステムが要求するインスタンスの数を指定する. desired capacity は,例えば 24 時間のリズムに合わせてインスタンスの数を増減させる (昼は多く夜は少なくなど) などの決まったスケジュールに基づいた設定を適用することができる. あるいはクラスター全体にかかっている負荷に応じて, desired capacity を動的に制御することも可能である. どのような基準でクラスターのスケーリングを行うかを定めるルールのことを,スケーリングポリシーとよぶ. たとえば,クラスター全体の稼働率 (負荷) を常に 80% に維持する,などのスケーリングポリシーが想定できる. この場合,クラスター全体の負荷が 80%を下回ったときにはクラスターからインスタンスが削除され,80%を超える (あるいは超えると予測される) 場合はインスタンスを追加する,という操作が ASG によって自動的に行われる.

    上記のようなパラメータを検討し,ユーザーは ASG を作成する. ASG を作成したのち, ECS との連携をプログラムしてあげることで, ECS を介して ASG による EC2 クラスターにタスクを投入することが可能になる.

    AWS Batch

    AWS Batch のアイコン

    先に説明したように, ECS と ASG を組み合わせることで,所望の計算クラスターを構築することが可能である. しかしながら, ECS と ASG にはかなり込み入った設定が必要であり,初心者にとっても経験者にとってもなかなか面倒なプログラミングが要求される. そこで, ECS と ASG によるクラスターの設計を自動化してくれるサービスが提供されている. それが AWS Batch である.

    AWS Batch はその名のとおりバッチ (Batch) 化されたジョブ (入力データだけが異なる独立した演算が繰り返し実行されること) を想定している. 多くの科学計算や機械学習がバッチ計算に当てはまる. たとえば,初期値のパラメータを変えて複数のシミュレーションを走らせる,といったケースだ. AWS Batch を用いることの利点は,クラスターのスケーリングやジョブの割り振りはすべて自動で実行され, ユーザーはクラウドの舞台裏の詳細を気にすることなく,大量のジョブを投入できるシステムが手に入る点である. が,知識として背後では ECS/ASG/EC2 の三つ巴が協調して動作しているという点は知っておいてほしい.

    AWS Batch では,ジョブの投入・管理をスムーズに行うため,次のような概念が定義されている (figure_title). まず, ジョブ (Job) というのが,AWS Batch によって実行される一つの計算の単位である. Job definitions とはジョブの内容を定義するものであり,これには実行されるべき Docker のイメージのアドレスや,割り当てる CPU・RAM の容量,環境変数などの設定が含まれる. Job definition に基づいて個々のジョブが実行される. ジョブが実行されると,ジョブは Job queues に入る. Job queues とは,実行待ち状態にあるジョブの列のことであり,時間的に最も先頭に投入されたジョブが最初に実行される. また,複数の queue を配置し, queue ごとに priority (優先度) を設定することが可能であり, priority の高い queue に溜まったジョブが優先的に実行される (筆者はこれをディズニーランドの"ファストパス"を連想して捉えている). Compute environment とは,先述したクラスターとほぼ同義の概念であり,計算が実行される場所 (EC2 や Fargate からなるクラスター) を指す. Compute environment には,使用する EC2 のインスタンスタイプや同時に起動するインスタンス数の上限などの簡易なスケーリングポリシーが指定されている. Job queues は Compute environment の空き状況を監視しており, それに応じてジョブを Compute environment に投下する.

    以上が AWS Batch を使用するうえで理解しておかなければならない概念であるが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは,実際に自分で手を動かしながら学んでいこう.

    AWS Batch の主要な概念

    EC2 or Fargate?

    ECS でクラスターを構成する際,計算を実行する場として EC2 と Fargate の二つの選択肢があることを説明した. それぞれ長所と短所を抱えているのだが,どのような場合にどちらを使うべきだろうか? それを検討するため,まずは table_title を見てみよう. これは EC2 と Fargate の特徴をまとめたものである. 説明の都合上,大幅な粗視化が行われている点は留意していただきたい.

    EC2 vs Fargate
    EC2Fargate

    Compute capacity

    Medium to large

    Small to medium

    GPU

    Yes

    No

    Launch speed

    Slow

    Fast

    Task placement flexibility

    Low

    High

    Programming complexity

    High

    Low

    これまでに見てきたように, EC2 は最大の CPU 数・メモリーサイズが大きかったり, GPU を利用できたりするなど,単一のインスタンスでの計算能力は高い. 対して, Fargate は単一インスタンスの最大 CPU 数は 4 コアが上限である. その一方で,インスタンスの起動に要する時間は Fargate のほうが圧倒的に早く,より俊敏にクラスターのスケーリングを行うことができる. また,タスクをクラスターに投入する際のフレキシビリティも Fargate のほうが高い. フレキシビリティというのは,例えば一つのインスタンスで 2 つ以上のコンテナを走らせる,などの状況である. 単位 CPU あたりで処理されるタスクの数を最大化する際には,このような設計がしばしば採用される. プログラミングの複雑さという観点からは, Fargate のほうが一般的にシンプルな実装になる.

    このように, EC2 と Fargate は互いに相補的な特性を有しており,アプリケーションによって最適な計算環境は検討される必要がある. また,EC2 と Fargate を両方用いたハイブリッドクラスターというのも定義可能であり,そのような選択肢もしばしば用いられる.

    準備

    ハンズオンのソースコードは GitHub の handson/aws-batch にある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.

    このハンズオンは, g4dn.xlarge タイプの EC2 インスタンスを使うので,アメリカ東部 (us-east-1) リージョンでは 0.526 $/hour のコストが発生する. 東京 (ap-northeast-1) を選択した場合は 0.71 $/hour のコストが発生する.

    準備 でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, 実践ディープラーニング! MNIST 手書き数字認識タスク で扱った MNIST 手書き文字認識の問題を再度取り上げよう. 実践ディープラーニング! MNIST 手書き数字認識タスク では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    ランダムサーチ法とは,ハイパーパラメータの組をある範囲の中でランダムに抽出し,大量に試行されたランダムな組の中から最適なパラメータの組を見出す方法である. すべての可能性を網羅的に探索できるわけではないが,調整すべきパラメータの数が多数ある場合に,グリッドサーチよりも効率的に広い探索空間をカバーすることができる.

    ベイズ最適化を用いた方法では,過去の探索結果から次にどの組み合わせを探索すべきかという指標を計算し,次に探索するパラメータを決定する. これにより,理論的にはグリッドサーチやランダムサーチ法よりも少ない試行回数で最適なパラメータにたどり着くことができる.

    並列化の観点でいうと,グリッドサーチとランダムサーチは各ハイパーパラメータの組の計算は独立に実行することができるため並列化が容易である. このように独立したジョブとして分割・並列化可能な問題を Embarrassingly parallel な問題とよぶ (直訳すると"恥ずかしいほど並列化可能な問題",ということになる). Embarrassingly parallel な問題はクラウドの強力な計算リソースを用いることで,非常なシンプルな実装で解くことができる. この章ではこのようなタイプの並列計算を取り上げる.

    一方,ベイズ最適化による方法は,過去の結果をもとに次の探索が決定されるので,並列化はそれほど単純ではない. 最近では optuna などのハイパーパラメータ探索のためのライブラリが発達しており,ベイズ最適化の数理的な処理を自動で実行してくれるので便利である. これらのライブラリを使うと,もし一台のコンピュータ (ノード) の中に複数の GPU が存在する場合は,並列に計算を実行することができる. しかしながら,一台のノードにとどまらず,複数のノードをまたいだ並列化は,高度なプログラミングテクニックが必要とされるだけでなく,ノード間の接続様式などクラウドのアーキテクチャにも深く依存するものである. 本書ではここまで高度なクラウドの使用方法には立ち入らない.

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に 実践ディープラーニング! MNIST 手書き数字認識タスク のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    sh
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. Hands-on #2: AWS でディープラーニングを実践 のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    sh
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドでは,--gpus all というパラメータが加わった.

    CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

    (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

    これはオーバーフィッティングとよばれる現象で,ニューラルネットが訓練データに過度に最適化され,訓練データの外のデータに対しての精度 (汎化性能) が向上していないことを示している. このような場合の対処法として, Early stopping とよばれるテクニックが知られている. Early stopping とは,検証データの Loss を追跡し,それが減少から増加に転じるエポックで学習をうち止め,そのエポックでのウェイトパラメータを採用する,というものである. 本ハンズオンでも, Early stopping によって訓練の終了を判断し,モデルの性能評価を行っていく.

    MNIST 手書き文字データセットでは,訓練データとして 60,000 枚,テストデータとして 10,000 枚の画像が与えられている. 本ハンズオンで使用するコードでは,訓練データのうち 80% の 48,000 枚を訓練データとして使用し,残り 20% の 12,000 枚を検証データとして用いている. 詳しくはソースコードを参照のこと.

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    アプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントは,あるハイパーパラメータの組を指定して Batch にジョブを提出する

    • Batch はジョブを受け取ると, EC2 からなるクラスターで計算を実行する

    • クラスター内では g4dn.xlarge インスタンスが起動する

    • Docker イメージは, AWS 内に用意された ECR (Elastic Container Registry) から取得される

    • 複数のジョブが投下された場合は,その数だけのインスタンスが起動し並列に実行される

    • 各ジョブによる計算の結果は S3 に保存される

    • 最後にクライアントは S3 から結果をダウンロードし,最適なハイパーパラメータの組を決定する

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    python
    class SimpleBatch(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    +
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
    +
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
    +
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
    +
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
    +
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
    +
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    class SimpleBatch(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    +
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
    +
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
    +
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
    +
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
    +
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
    +
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    • で,計算結果を保存するための S3 バケットを用意している

    • で, Compute environment を定義している. ここでは g4dn.xlarge のインスタンスタイプを使用するとし,最大の vCPU 使用数は 64 と指定している. また,最小の vCPU は 0 である. 今回は,負荷がかかっていないときにアイドリング状態にあるインスタンスを用意する利点は全くないので,ここは 0 にするのが望ましい.

    • で, <2> で作成した Compute environment と紐付いた Job queue を定義している.

    • で,ジョブが計算結果を S3 に書き込むことができるよう, IAM ロールを定義している. (IAM とはリソースがもつ権限を管理する仕組みである.詳しくは AWS における権限の管理 (IAM) を参照)

    • では, Docker image を配置するための ECR を定義している.

    • で Job definition を作成している. ここでは,4 vCPU, 12000 MB (=12GB) の RAM を使用するように指定している. また,今後必要となる環境変数 (BUCKET_NAME) を設定している. さらに, <4> で作った IAM を付与している.

    g4dn.xlarge は 1 台あたり 4 vCPU が割り当てられている. このプログラムでは Compute environment の maximum vCPUs を 64 と指定しているので,最大で 16 台のインスタンスが同時に起動することになる. ここで maxium vCPUs を 64 に限定しているのは,なんらかのミスで意図せぬジョブを大量にクラスターに投入してしまった事態で,高額の AWS 利用料金が発生するのを防ぐためである. もし,自分のアプリケーションで必要と判断したならば自己責任において 64 よりも大きな数を設定して構わない.

    ここで注意が一点ある. AWS では各アカウントごとに EC2 で起動できるインスタンスの上限が設定されている. この上限は AWS コンソールにログインし, EC2 コンソールの左側メニューバーの Limits をクリックすることで確認できる (figure_title). g4dn.xlarge (EC2 の区分でいうと G ファミリーに属する) の制限を確認するには, Running On-Demand All G instances という名前の項目を見る. ここにある数字が, AWS によって課されたアカウントの上限であり,この上限を超えたインスタンスを起動することはできない. もし,自分の用途に対して上限が低すぎる場合は,上限の緩和申請を行うことができる. 詳しくは 公式ドキュメンテーション "Amazon EC2 service quotas" を参照のこと.

    EC2コンソールから各種の上限を確認する

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    次に,Job queue overview にある SimpleBatch-queue という項目に注目してほしい. ここでは実行待ちのジョブ・実行中のジョブ・実行が完了したジョブを一覧で確認することができる. PENDING, RUNNING, SUCCEEDED, FAILED などのカラムがあることが確認できる.ジョブが進行するにつれて,ジョブの状態がこのカラムにしたがって遷移していく. 後でジョブを実際にサブミットしたときに戻ってこよう.

    最後に,今回作成した Job definition を確認しよう. 左側のメニューから Job definitions を選択し,次の画面で SimpleBatchjob-definition という項目を見つけて開く. ここから Job definition の詳細を閲覧することができる (figure_title). 中でも重要な情報としては, vCPUs, Memory, GPU がそれぞれ Docker に割り当てられる vCPU・メモリー・ GPU の量を規定している. また, Image と書いてあるところに,ジョブで使用される Docker イメージが指定されている. ここでは, ECR のレポジトリを参照している. 現時点ではこの ECR は空である. 次のステップとして,この ECR にイメージを配置する作業を行おう.

    AWS Batch から Job definition を確認

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン (Hands-on #3: AWS で自動質問回答ボットを走らせる) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    python
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
    +
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
    +
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    • で,新規の ECR を作成している.

    • で Job definition を定義する中で,イメージを <1> で作った ECR から取得するように指定している. これと同時に, Job definition には ECR へのアクセス権限が IAM を通じて自動的に付与される.

    さて,スタックをデプロイした時点では, ECR は空っぽである. ここに自分のアプリケーションで使う Docker イメージを push してあげる必要がある.

    そのために,まずは AWS コンソールから ECR の画面を開こう (検索バーに Elastic Container Registry と入力すると出てくる). Private というタブを選択すると, simplebatch-repositoryXXXXXX という名前のレポジトリが見つかるだろう (figure_title).

    ECR のコンソール画面

    次に,このレポジトリの名前をクリックするとレポジトリの詳細画面に遷移する. そうしたら,画面右上にある View push commands というボタンをクリックする. すると figure_title のようなポップアップ画面が立ち上がる.

    ECR への push コマンド

    このポップアップ画面で表示されている四つのコマンドを順番に実行していくことで,手元の Docker イメージを ECR に push することができる. push を実行する前に, AWS の認証情報が設定されていることを確認しよう. そのうえで,ハンズオンのソースコードの中にある docker/ という名前のディレクトリに移動する. そうしたら,ポップアップ画面で表示されたコマンドを上から順に実行していく.

    ポップアップで表示されるコマンドの 2 つめを見てみると docker build -t XXXXX . となっている. 最後の . が重要で,これは 現在のディレクトリにある Dockerfile を使ってイメージをビルドせよ という意味である. このような理由で, Dockerfile が置いてあるディレクトリに移動する必要がある.

    四つ目のコマンドは,数 GB あるイメージを ECR にアップロードするので少し時間がかかるかもしれないが,これが完了するとめでたくイメージが ECR に配置されたことになる. もう一度 ECR のコンソールを見てみると,確かにイメージが配置されていることが確認できる (figure_title). これで,AWS Batch を使ってジョブを実行させるための最後の準備が完了した.

    ECR へ image の配置が完了した

    単一のジョブを実行する

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    sh
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    python
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
    +
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
    +
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    python
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    python
    # [4]
    +submit_job(0.01, 0.1, 100)
    # [4]
    +submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは AWS CLI のインストール), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    AWS Batch でジョブが実行されている様子

    figure_title で赤で囲った箇所に注目してほしい. 一つのジョブが投入されると,それは SUBMITTED という状態を経て RUNNABLE という状態に遷移する. RUNNABLE とは, ジョブを実行するためのインスタンスが Compute environment に不足しているため,新たなインスタンスが起動されるのを待っている状態に相当する. インスタンスの準備が整うと,ジョブの状態は STARTING を経て RUNNING に至る.

    次に,ジョブのステータスが RUNNING のときの Compute environment の Desired vCPU を見てみよう (figure_title で紫で囲った箇所). ここで 4 と表示されているのは, g4dn.xlarge インスタンス一つ分の vCPU の数である. ジョブの投入に応じて,それを実行するのに最低限必要な EC2 インスタンスが起動されたことが確認できる (興味のある人は, EC2 コンソールも同時に覗いてみるとよい).

    しばらく経つと,ジョブの状態は RUNNING から SUCCEEDED (あるいは何らかの理由でエラーが発生したときには FAILED) に遷移する. 今回のハンズオンで使っている MNIST の学習はだいたい 10 分くらいで完了するはずである. ジョブの状態が SUCCEEDED になるまで見届けよう.

    ジョブが完了すると,学習の結果 (エポックごとの Loss と Accuracy を記録した CSV ファイル) は S3 に保存される. AWS コンソールからこれを確認しよう.

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    python
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    python
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
    +
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
    +
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
    +
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
    +
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
    +
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
    +
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    python
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...
    # [1]
    +import boto3
    +import argparse
    +
    +# [2]
    +# AWS 認証ヘルパー ...省略...
    +
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    python
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    複数のジョブを同時投入したときの Job 一覧

    今度は EC2 コンソールを見てみよう. 左のメニューから Instances を選択すると, figure_title に示すような起動中のインスタンスの一覧が表示される. g4dn.xlarge が 9 台稼働しているのが確認できる. Batch がジョブの投下に合わせて必要な数のインスタンスを起動してくれたのだ!

    複数のジョブを同時投入したときの EC2 インスタンスの一覧

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    python
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
    +
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
    +
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
    +
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
    +
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
    +
    +    return df
    +
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
    +
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
    +
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    今回のパラメータサーチは勉強用に極めて単純化されたものである点は承知いただきたい.

    たとえば,今回は学習率が 0.1 が最も良いとされたが,それは訓練のエポックを 100 に限定しているからかもしれない. 学習率が低いとその分訓練に必要なエポック数も多くなる. 訓練のエポック数をもっと増やせばまた違った結果が観察される可能性はある.

    また,今回は MNIST の訓練データ 60,000 枚のうち, 48,000 枚を訓練データ,残り 12,000 枚を検証データとして用いた. この分割は乱数を固定してランダムに行ったが,もしこの分割によるデータのバイアスを気にするならば, k 個の異なる学習・検証データの分割をあらかじめ用意して,複数回モデルの評価を行う (k-fold cross-validation) 方法も,より精緻なアプローチとして考えられる.

    以上のようにして, CNN を用いた MNIST 分類モデルのハイパーパラメータの最適化の一連の流れを体験した. AWS Batch を利用することで,比較的少ないプログラミングで,動的に EC2 クラスターを制御し,並列にジョブを処理するシステムが構築できた. ここまで EC2 を使いこなすことができれば,多くの問題を自力で解くことが可能になるだろう!

    スタックの削除

    これにて,本ハンズオンは終了である.最後にスタックを削除しよう. 今回のスタックを削除するにあたり,ECR に配置された Docker のイメージは手動で削除されなければならない (これをしないと, cdk destroy を実行したときにエラーになってしまう. これは CloudFormation の仕様なので従うしかない).

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, Hands-on #2: AWS でディープラーニングを実践 で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを Hands-on #3: AWS で自動質問回答ボットを走らせる を参考に構築する.

    実際,本書ではこの流れに沿って演習を進めてきた. MNIST タスクを解くモデルを,最初 Jupyter Notebook を使用して実験し,そのコードをほとんどそのまま Docker にパッケージし, AWS Batch を用いてハイパーパラメータサーチを行った. このサイクルを繰り返すことで,クラウドを最大限に活用した機械学習アプリケーションの開発を進めることができる.

    クラウドを活用した機械学習アプリケーションの開発フロー

    小括

    ここまでが,本書第二部の内容である. 第一部に引き続き盛りだくさんの内容であったが,ついてこれたであろうか?

    第二部ではまず最初に,深層学習の計算をクラウドで実行するため, GPU 搭載型の EC2 インスタンスの起動について解説した. さらに,ハンズオンでは,クラウドに起動した仮想サーバーを使って MNIST 文字認識タスクを解くニューラルネットを訓練した (Hands-on #2: AWS でディープラーニングを実践).

    また,より大規模な機械学習アプリケーションを作るための手段として, Docker と ECS によるクラスターの初歩を説明した (Docker 入門). その応用として,英語で与えられた文章問題への回答を自動で生成するボットをクラウドに展開した (Hands-on #3: AWS で自動質問回答ボットを走らせる). タスクの投入に応じて動的に計算リソースが作成・削除される様子を実際に体験できただろう.

    さらに, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する では AWS Batch を用いてニューラルネットの学習を並列に実行する方法を紹介した. ここで紹介した方法は,ミニマムであるが,計算機システムを大規模化していくためのエッセンスが網羅されている. これらのハンズオン体験から,クラウド技術を応用してどのように現実世界の問題を解いていくのか,なんとなくイメージが伝わっただろうか?

    本書の第三部では,さらにレベルアップし,サーバーレスアーキテクチャという最新のクラウドの設計手法について解説する. その応用として,ハンズオンでは簡単な SNS サービスをゼロから実装する. 引き続きクラウドの最先端の世界を楽しんでいこう!

    Web サービスの作り方

    ここからが,本書第三部の内容になる. これまでのセクションでは,仮想サーバーをクラウド上に起動し,そこで計算を走らせる方法について解説をしてきた. EC2, ECS, Fargate, Batch などを利用して,動的にスケールするクラスターを構成し,並列にタスクを実行するクラウドシステムを実装してきた. 振り返ると,これまで紹介してきた内容は,自分自身が行いたい計算をクラウドを駆使することで実現する,という用途にフォーカスしていたことに気がつくだろう. 一方で,広く一般の人々に使ってもらえるような計算サービス・データベースを提供する,というのもクラウドの重要な役割として挙げられる.

    本章から始まる第三部では,前回までとは少し方向性を変え,どのようにしてクラウド上にアプリケーションを展開し,広く一般の人に使ってもらうか,という点を講義したいと思う. これを通じて,どのようにして世の中のウェブサービスができ上がっているのかを知り,さらにどうやって自分でそのようなアプリケーションをゼロから構築するのか,という点を学んでもらう. その過程で,サーバーレスアーキテクチャという最新のクラウド設計手法を解説する.

    その前準備として,本章ではどのようにしてウェブサービスが出来上がっているのか,その背後にある技術の概要を解説する. 用語の解説が中心となるが,後のハンズオンを実装するために必須の知識であるので,理解して前に進むよう心がけよう.

    ウェブサービスの仕組み  — Twitter を例に

    あなたがパソコンやスマートフォンから Twitter, Facebook, YouTube などのウェブサービスにアクセスしたとき,実際にどのようなことが行われ,コンテンツが提示されているのだろうか?

    HTTP を通じたサーバーとクライアントのデータのやり取りは,すでに知っている読者も多いだろうし,逆にすべて解説しようとすると紙面が足りないので,ここではエッセンスの説明のみにとどめる. 以降では Twitter を具体例として,背後にあるサーバーとクライアントの間の通信を概説しよう. 概念図としては figure_title のような通信がクライアントとサーバーの間で行われていることになる.

    クライアントと Web サーバーの通信の概念図

    前提として,クライアントとサーバーの通信は HTTP (Hypertext Transfer Protocol) を使って行われる. また,最近では,暗号化された HTTP である HTTPS (HTTPS (Hypertext Transfer Protocol Secure)) を用いることがスタンダードになってきている. 第一のステップとして,クライアントは HTTP(S) 通信によってサーバーから静的なコンテンツを取得する. 静的なコンテンツとは, HTML (Hyptertext Markup Language) で記述されたウェブページの文書本体, CSS (Cascading Style Sheets) で記述されたページのデザインやレイアウトファイル,そして JavaScript (JS) で記述されたページの動的な挙動を定義したプログラム,が含まれる. Twitter を含む現代的なウェブアプリケーションの設計では,この静的なファイル群はページの”枠”を定義するだけで,中身となるコンテンツ (例: ツイートの一覧) は別途 API (Application Programming Interface) によって取得されなければならない. そこで,クライアントは先のステップで取得された JavaScript で定義されたプログラムに従って,サーバーに API を送信し,ツイートや画像データを取得する. この際,テキストデータのやり取りには JSON (JavaScript Object Notation) というフォーマットが用いられることが多い. 画像や動画などのコンテンツも同様に API により取得される. このようにして取得されたテキストや画像が,HTML の文書に埋め込まれることで,最終的にユーザーに提示されるページが完成するのである. また,新しいツイートを投稿するときにも,クライアントから API を通じてサーバーのデータベースにデータが書き込まれる.

    REST API

    API (Application Programming Interface) とはこれまで何度も出てきた言葉であるが,ここではよりフォーマルな定義付けを行う. API とはあるソフトウェア・アプリケーションが,外部のソフトウェアに対してコマンドやデータをやり取りするための媒介の一般的総称である. とくに,ウェブサービスの文脈では,サーバーが外界に対して提示しているコマンドの一覧のことを意味する. クライアントは,提示されている API から適切なコマンドを使うことによって,所望のデータを取得したり,あるいはサーバーにデータを送信したりする.

    とくに,ウェブの文脈では REST (Representational State Transfer) とよばれる設計思想に基づいた API が現在では最も一般的に使われている. REST の設計指針に従った API のことを REST API あるいは RESTful API とよんだりする.

    REST API は, figure_title に示したような MethodURI (Universal Resource Identifier) の組からなる.

    REST API

    Method (メソッド) とは,どのような操作を行いたいかを抽象的に表す,"動詞" として捉えることができる. メソッドには HTTP 規格で定義された 9 個の動詞 (verb) を使用することができる. この中でも, GET, POST, PUT, PATCH, DELETE の 5 個が最も頻繁に使用される (table_title). この 5 つのメソッドによる操作を総称して CRUD (create, read, update, and delete) とよぶ.

    REST API Methods
    メソッド意図される動作

    GET

    要素を取得する

    POST

    新しい要素を作成する

    PUT

    既存の要素を新しい要素と置き換える

    PATCH

    既存の要素の一部を更新する

    DELETE

    要素を削除する

    一方, URI は操作が行われる対象,すなわち "目的語" を表す. ウェブの文脈では操作が行われる対象のことをしばしば リソース とよぶ. URI は多くの場合 http または https から始まるウェブサーバーのアドレスから始まり, / (スラッシュ) 以降に所望のリソースのパスが指定される. figure_title の例で言えば, https://api.twitter.com というアドレスの /1.1/status/home_timeline というリソースを取得 (GET) せよ,という意味になる (なお,ここで 1.1 という数字は API のバージョンを示している). この API リクエストによって,ユーザーのホームのタイムラインのツイートの一覧が取得される.

    REST API のメソッドには, table_title で挙げたもの以外に, HTTP プロトコルで定義されているほかのメソッド (OPTIONS, TRACE など) を用いることもできるが,あまり一般的ではない.

    また,これらのメソッドだけでは動詞として表現しきれないこともあるが, URI の名前でより意味を明確にすることもある. メソッドの使い方も,要素を削除する際は必ず DELETE を使わなければならない,という決まりもなく,たとえば, Twitter API でツイートを消す API は POST statuses/destroy/:id で定義されている. 最終的には,各ウェブサービスが公開している API ドキュメンテーションを読んで,それぞれの API がどんな操作をするのかを調べる必要がある.

    REST の概念は 2000 年代初頭に確立され,今日の API 設計のスタンダードとなった. 一方で,ウェブのテクノロジーが進歩するにつれて,新たな API の設計アプローチの需要も高まっている. 近年とくに人気を集めているのが, GraphQL と呼ばれる API の設計方法である. GraphQL は Facebook 社によって最初に作られ,現在は GraghQL Foundation によって維持と更新がされている. GraphQL を使用すると,クライアントは REST と比較してより柔軟性の高いデータのクエリを行うことができるなど,いくつかの利点がある. キーワードだけでも知っておくと,今後役に立つだろう.

    Twitter API

    もう少し具体的にウェブサービスの API を体験する目的で,ここでは Twitter の API を見てみよう. Twitter が提供している API の一覧は Twitter の Developer Documentation で見ることができる. いくつかの代表的な API を table_title にまとめた.

    Twitter API
    エンドポイント動作

    GET statuses/home_timeline

    ホームのタイムラインのツイートの一覧を取得する.

    GET statuses/show/:id

    :id で指定されたツイートの詳細情報を取得する.

    GET search

    ツイートの検索を実行する.

    POST statuses/update

    新しいツイートを投稿する.

    POST media/upload

    画像をアップロードする

    POST statuses/destroy/:id

    :id で指定されたツイートを削除する.

    POST statuses/retweet/:id

    :id で指定されたツイートをリツイートする.

    POST statuses/unretweet/:id

    :id で指定されたツイートのリツイートを取り消す.

    POST favorites/create

    選択したツイートを"いいね"する.

    POST favorites/destroy

    選択したツイートを"いいね"を取り消す.

    この API リストをもとに, Twitter のアプリまたはウェブサイトを開いたときに起こるクライアントとサーバーの通信をシミュレートしてみよう.

    ユーザーが Twitter を開くと,まず最初に GET statuses/home_timeline の API リクエストによって,ユーザーのホームのタイムラインのツイートのリストが取得される. 個々のツイートは JSON 形式のデータになっており, id, text, user, coordinates, entities などの属性を含む. id はツイートに固有な ID を表し, text はツイートの本文を含んでいる. user はツイートを投稿したユーザーの名前やプロフィール画像の URL などを含んだ JSON データになっている. coordinates にはツイートが発信された地理的な座標が記録されている. また, entities にはツイートに関連するメディアファイル (画像など) のリンクなどの情報が埋め込まれている. GET statuses/home_timeline からは直近のツイートのリスト (リストが長すぎる場合は途中で切られたもの) が取得される. もしツイートの ID を知っている場合は GET statuses/show/:id を呼ぶことによって, :id パラメータで指定された特定のツイートを取得することができる.

    ツイートの検索を行うためには GET search API を使用する. この API には,ツイートに含まれる単語や,ハッシュタグ,ツイートの発信された日時や場所など,様々なクエリの条件を渡すことができる. API からは, GET statuses/home_timeline などと同様, JSON 形式のツイートのデータが返される.

    ユーザーが新しいツイートを投稿するには POST statuses/update のエンドポイントを利用する. POST statuses/update には,ツイートの文章や,リプライの場合はリプライ先のツイートの ID などのデータを送信する. また,ツイートに画像データを添付したい場合は, POST media/upload を併せて使用する. ツイートの削除を行うには, POST statuses/destroy/:id を用いる.

    そのほか,頻繁に行われる操作としては, POST statuses/retweet/:idPOST statuses/unretweet/:id がある. これらは, :id で指定されるツイートに対して,それぞれリツイートを実行あるいは取り消すための API である. また, POST favorites/createPOST favorites/destroy を使用することによって,選択されたツイートに"いいね"を追加したり,取り消したりする操作を行う.

    このような一連の操作が, Twitter のアプリの背後では行われている. また,自分自身でボットを作成したい場合は,これらの API を適切に組み合わせ,カスタムのプログラムを書くことで実現される.

    このように, API はあらゆるウェブサービスを作るうえで一番基礎となる要素である. 次からの章では本章で紹介した用語が何度も出てくるので,頭の片隅に置いたうえで読み進めていただきたい.

    Serverless architecture

    サーバーレスアーキテクチャ (Serverless architecture) あるいは サーバーレスコンピューティング (Serverless computing) とは,従来とは全く異なるアプローチに基づくクラウドシステムの設計方法である. 歴史的には, AWS が 2014 年に発表した Lamba がサーバーレスアーキテクチャの先駆けとされている. その後, Google や Microsoft などのクラウドプラットフォームも同様の機能の提供を開始している. サーバーレスアーキテクチャの利点は,スケーラブルなクラウドシステムを安価かつ簡易に作成できる点であり,近年いたるところで導入が進んでいる.

    Serverless とは,文字どおりの意味としてはサーバーなしで計算をするということになるが,それは一体どういう意味だろうか? サーバーレスについて説明するためには,まずは従来的な, "serverful" とよばれるようなシステムについて解説しなければならない.

    Serverful クラウド (従来型)

    従来的なクラウドシステムのスケッチを figure_title に示す. クライアントから送信されたリクエストは,最初に API サーバーに送られる. API サーバーでは,リクエストの内容に応じてタスクが実行される. タスクには,API サーバーだけで完結できるものもあるが,多くの場合,データベースの読み書きが必要である. データベースには,データベース専用の独立したサーバーマシンが用いられることが一般的である. また,画像や動画などの容量の大きいデータは,また別のストレージサーバーに保存されることが多い. これらの API サーバー,データベースサーバー,ストレージサーバーはそれぞれ独立したサーバーマシンであり, AWS の言葉では EC2 による仮想インスタンスを想定してもらったらよい.

    多くのウェブサービスでは,多数のクライアントからのリクエストを処理するため,複数のサーバーマシンがクラウド内で起動し,負荷を分散するような設計がなされている. クライアントから来たリクエストを計算容量に余裕のあるサーバーに振り分けるような操作を Load balancing とよび,そのような操作を担当するマシンのことを Load balancer という.

    計算負荷を分散する目的で多数のインスタンスを起動するのはよいのだが,計算負荷が小さすぎてアイドリング状態にあるようではコストと電力の無駄遣いである. したがって,すべてのサーバーが常に目標とする計算負荷を維持するよう,計算の負荷に応じてクラスター内の仮想サーバーの数を動的に増減させるような仕組みが必要である. そのような仕組みをクラスターのスケーリングとよび,負荷の増大に応答して新しい仮想インスタンスをクラスターに追加する操作を scale-out,負荷の減少に応答してインスタンスをシャットダウンする操作を scale-in とよぶ. クラスターのスケーリングは, API サーバーではもちろんのこと,データベースサーバー・ストレージサーバーでも必要になる. ストレージサーバーでは,例えば頻繁にアクセスされるデータはキャッシュ領域に保存したり,データのコピーを複数作るなどのスケーリングが行われる. データベースサーバーも同様に,頻繁にアクセスされるデータのアクセスがパンクしてしまわないよう,分散的な処理が必要となる. このように,クラウドシステム内すべての箇所で,負荷が均一になるような調整が必要であり,開発者は多くの時間をそのチューニングに費やさなければならない. また,サービスの利用者の数などに応じてスケーリングの設定は常に見直される必要があり,継続的な開発が要求される.

    さらに問題を複雑にするのは,API サーバーで処理されるべきタスクが,非一様な点である. 非一様であるとは,たとえばタスク A は 3000 ミリ秒の実行時間と 512MB のメモリーを消費し,別のタスク B は 1000 ミリ秒の実行時間と 128MB のメモリーを消費する,というような状況を指している. 一つのサーバーマシンが計算負荷が異なる複数のタスクを処理する場合,クラスターのスケーリングはより複雑になる. この状況をシンプルにするために,1サーバーで実行するタスクは1種類に限る,という設計も可能であるが,そうするとで生まれる弊害も多い (ほとんど使われないタスクに対してもサーバー一台をまるまる割り当てなければならない = ほとんどアイドリング状態になってしまう,など).

    Serverful なクラウドシステム

    Serverless クラウドへ

    Serverful クラウド (従来型) で議論したように,クラスターのスケーリングはクラウドシステムの経済的効率とシステムの安定性を最大化するために必須の作業である. それを反映して,多くの開発者の時間が投資されてきた.

    クラスターのスケーリングはすべての開発者が何度も繰り返し行ってきた作業であり,いくつかの側面をテンプレート化し,共通化することができたならば開発のコストを大幅に削減できるだろう. それを実現するには,根本的なレベルからクラウドシステムの設計を考え直す必要がある. スケーリングを前提として考えることで,もっとシンプルで見通しがよいクラウドシステムの設計の仕組みはないだろうか? そのような動機が,サーバーレスアーキテクチャが誕生する背後にあった.

    従来の serverful なシステムでの最大の問題点は,サーバーをまるまる占有してしまうという点にある. すなわち, EC2 インスタンスを起動したとき,そのインスタンスは起動したユーザーだけが使えるものであり,計算のリソース (CPU や RAM) が独占的に割り当てられた状態になる. 固定した計算資源の割り当てがされてしまっているので,インスタンスの計算負荷が 0%であろうが 100%であろうが,均一の使用料金が起動時間に比例して発生する.

    サーバーレスアーキテクチャは,このような 独占的に割り当てられた計算リソースというものを完全に廃止することを出発点とする. サーバーレスアーキテクチャでは,計算のリソースは,クラウドプロバイダーがすべて管理する. クライアントは,仮想インスタンスを一台まるごと借りるのではなく,計算のタスクの需要が生まれる毎に,実行したいプログラム・コマンドをクラウドに提出する. クラウドプロバイダーは,自身のもつ巨大な計算リソースから空きを探し,提出されたプログラムを実行し,実行結果をクライアントに返す. 言い換えると,計算リソースのスケーリングやアロケーションなどはクラウドプロバイダーが一手に引き受け,ユーザーはジョブをサブミットすることに注力する,という枠組みである. これを図示すると, figure_title のようになる.

    従来のクラウドと Serverless クラウドの比較

    サーバーレスクラウドでは,スケーリングはすべてクラウドプロバイダーが引き受けるので,スケーラビリティーが保証されている. クライアントが同時に大量のタスクを送信した場合でも,クラウドプロバイダー側の独自の仕組みによってすべてのタスクが遅延なく実行される. また,サーバーレスクラウドを利用することで,クラウドのコストは実際に使用した計算の総量 (稼働時間) で決定されることになる. これは,計算の実行総量に関わらずインスタンスの起動時間で料金が決定されていた従来のシステムと比べて大きな違いである.

    サーバーレスクラウドは,従来のクラウドとは根本から異なったアプローチなので,コードの書き方やシステムの設計が大きく異なる. サーバーレスクラウドを開発・運用するには,サーバーレス固有の概念や用語に精通している必要がある. 以降では,実際にクラウドを動かしながら,サーバーレスをより具体的に体験していこう.

    従来型の(仮想インスタンスをたくさん起動するような)クラウドシステムは,賃貸と似ているかもしれない. 部屋を借りるというのは,その部屋でどれだけの時間を過ごそうが,月々の家賃は一定である. 同様に,仮想サーバーも,それがどれほどの計算を行っているかに関わらず,一定の料金が時間ごとに発生する.

    一方で,サーバーレスクラウドは,電気・水道・ガス料金 と似ている. こちらは,実際に使用した量に比例して料金が決定されている. サーバーレスクラウドも,実際に計算を行った総時間で料金が決まる仕組みになっている.

    サーバーレスクラウドを構成するコンポーネント

    サーバーレスアーキテクチャの概要がわかってきたところで,ここでは AWS においてサーバーレスクラウドを構成する様々なコンポーネントを紹介していこう. 特に, Lambda, S3, DynamoDB を取り上げ,解説する (figure_title). サーバーレスクラウドは,これらのコンポーネントを統合することで一つのシステムが出来上がる. ここでは, Lambda,S3,DynamoDB を利用する際に押さえておかなければならない知識を一通り説明しきる都合上,具体的なイメージがわきにくいかもしれない. が,続く Hands-on #5: サーバーレス入門 でそれぞれについてハンズオン形式で演習を行うので,そこでさらに理解を深めれば大丈夫である.

    Lambda, S3, DynamoDB のアイコン

    Lambda

    AWS でサーバーレスコンピューティングの中心を担うのが, Lambda である. Lambda の使い方を figure_title に図示している. Lambda の仕組みはシンプルで,まずユーザーは実行したいプログラムのコードを事前に登録しておく. プログラムは, Python, Node.js, Ruby などの主要な言語がサポートされている. Lambda に登録されたひとつひとつのプログラムを関数 (Function) とよぶ. そして,関数を実行したいときに,invoke コマンドを Lambda に送信する. Lambda では, invoke のリクエストを受け取るとただちに (数ミリセカンドから数百ミリセカンド程度の時間で) プログラムの実行を開始する. そして,実行結果をクライアントやその他の計算機に返す.

    AWS Lambda

    このように,Lambda では占有された仮想インスタンスは存在せず,実行を待っているプログラムだけがある状態である. invoke のリクエストに応じて,プログラムが AWS の巨大な計算機プールのどこかに配置され,実行される. 同時に複数のリクエストが来た場合でも, AWS はそれらを実行するための計算リソースを割り当て,並列的に処理を行ってくれる. 原理上は,数千から数万のリクエストが同時に来たとしても, Lambda はそれらを同時に実行することができる. このような,占有された仮想サーバーの存在なしに,動的に関数を実行するサービスのことを総称して FaaS (Function as a Service) とよぶ.

    Lambda ではそれぞれの関数につき, 128MB から 10240MB のメモリーを使用することができる (執筆時点の仕様). また,実効的な CPU のパワーはメモリーの量に比例する形で割り当てられる. すなわち,タスクに割り当てたメモリーの量が多ければ多いほど,より多くの CPU リソースが割り当てられることになる (しかし, RAM と CPU パワーの具体的な換算表は AWS からは公開されていない). 実行時間は 100 ミリ秒の単位で記録され,実行時間に比例して料金が決定される. table_title は Lambda の利用料金表である (執筆時点で ap-north-east1 リージョンを選択した場合).

    Lambda の料金表
    Memory (MB)Price per 100ms

    128

    $0.0000002083

    512

    $0.0000008333

    1024

    $0.0000016667

    3008

    $0.0000048958

    実行時間に比例する料金に追加して,リクエストを送信するごとに発生する料金が設定されている. これは,百万回のリクエストにつき $0.2 である. たとえば, 128MB のメモリーを使用する関数を,それぞれ 200 ミリ秒,合計で 100 万回実行した場合, 0.0000002083 * 2 * 10^6 + 0.2 = $0.6 の料金となる. ウェブサーバーのデータベースの更新など簡単な計算であれば,200 ミリ秒程度で実行できる関数も多いことから,100 万回データベースの更新を行ったとしても,たった $0.6 しかコストが発生しないことになる. また,コードが実行されず待機状態になっている場合は,発生する料金は 0 である. このように,実際に意味のある処理が行われた時間にのみ,料金が発生する仕組みになっている.

    Lambda は比較的短時間で完了する,反復性の高いタスクの実行に向いている. データベースの読み書きはその典型的な例であるが,そのほかにも,画像のサイズをトリミングしたり,サーバーサイドで定期的に実行されるメンテナンス処理などの利用が考えられる. また,複数の Lambda をリレー式に繋げることも可能で,シンプルな処理を組み合わせることで複雑なロジックを表現することができる.

    上述の Lambda の料金計算は,説明のためコストに寄与する要素をいくつか省いている点は承知いただきたい. 例えば, DynamoDB の読み書きに関する料金や,ネットワークの通信にかかわるコストが考慮されていない.

    サーバーレスストレージ: S3

    サーバーレスの概念は,ストレージにも拡張されている.

    従来的なストレージ (ファイルシステム) では,必ずホストとなるマシンと OS が存在しなければならない. したがって,それほどパワーは必要ないまでも,ある程度の CPU リソースを割かなければならない. また,従来的なファイルシステムでは,データ領域のサイズは最初にディスクを初期化するときに決めなければならず,後から容量を増加させることはしばしば困難である (ZFS などのファイルシステムを使えばある程度は自由にファイルシステムのサイズを変更することは可能である). よって,従来的なクラウドでは,ストレージを借りる際にはあらかじめディスクのサイズを指定せねばならず,ディスクの中身が空であろうと満杯であろうと,同じ利用料金が発生することになる (figure_title).

    Simple Storage Service (S3) は,サーバーレスなストレージシステムを提供する (figure_title). S3 は従来的なストレージシステムと異なり, OS に"マウントする”という概念はない. 基本的に API を通じてデータの読み書きの操作が行われる. また,データの冗長化や暗号化,バックアップの作成など,通常ならば OS と CPU が介在しなければならない操作も, API を通じて行うことができる. S3 では事前に決められたディスク領域のサイズはなく,データを入れれば入れた分だけ,保存領域は拡大していく (仕様上はペタバイトスケールのデータを保存することが可能である). ストレージにかかる料金は,保存してあるデータの総容量で決定される.

    S3 と従来的なファイルシステムの比較

    S3 を利用する際に,料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 説明のため主要な事項のみ取り出している. 詳細は 公式ドキュメンテーション "Amazon S3 pricing" を参照).

    S3 の利用料金
    項目料金

    Data storage (First 50TB)

    $0.023 per GB per month

    PUT, COPY, POST, LIST requests (per 1,000 requests)

    $0.005

    GET, SELECT, and all other requests (per 1,000 requests)

    $0.0004

    Data Transfer IN To Amazon S3 From Internet

    $0

    Data Transfer OUT From Amazon S3 To Internet

    $0.09 per GB

    第一に,データの保存には $0.025 per GB のコストが月ごとに発生する. したがって,1000GB のデータを S3 に一ヵ月保存した場合, $25 の料金が発生することになる. また,PUT, COPY, POST などのリクエスト (=データを書き込む操作) に対しては,データ容量に関係なく,1000 回ごとに $0.005 のコストが発生する. GET, SELECT などのリクエスト (=データを読み込む操作) に対しては,1000 回ごとに $0.0004 のコストが発生する. また, S3 はデータを外に取り出す際の通信にもコストが生じる. 執筆時点では,S3 からインターネットを通じて外部にデータを転送 (data-out) すると $0.09 per GB のコストが発生する. データをインターネットを通じて S3 に入れる (data-in) 通信は無料で行える. また, AWS の 同じ Region 内のサービス (Lambda や EC2 など) にデータを転送するのは無料である. AWS のリージョンをまたいだデータの転送にはコストが発生する. いずれにせよ,サーバーレスの概念に則り,すべての料金が従量課金制で決定される設定になっている.

    サーバーレスデータベース: DynamoDB

    サーバーレスの概念は,データベースにも適用することができる.

    ここでいうデータベースとは, Web サービスなどにおけるユーザーや商品の情報を記録しておくための保存領域のことを指している. 従来的に有名なデータベースとしては MySQL, PostgreSQL, MongoDB などが挙げられる. データベースと普通のストレージの違いは,データの検索機能にある. 普通のストレージではデータは単純にディスクに書き込まれるだけだが, データベースでは検索がより効率的になるようなデータの配置がされたり, 頻繁にアクセスされるデータはメモリーにキャッシュされるなどの機能が備わっている. これにより,巨大なデータの中から,興味のある要素を高速に取得することができる.

    このような検索機能を実現するには,当然 CPU の存在が必須である. したがって,従来的なデータベースを構築する際は,ストレージ領域に加えて,たくさんの CPU コアを搭載したマシンが用いられることが多い. また,データベースが巨大な場合は複数マシンにまたがった分散型のシステムが設計される. 分散型システムの場合は, Serverful クラウド (従来型) で議論したようにデータベースへのアクセス負荷に応じて適切なスケーリングがなされる必要がある.

    DynamoDB は, AWS が提供しているサーバーレスな分散型データベースである. サーバーレスであるので,占有されたデータベース用仮想インスタンスは存在せず, API を通じてデータの書き込み・読み出し・検索などの操作を行う. S3 と同様に,データ保存領域の上限は定められておらず,データを入れれば入れた分だけ,保存領域は拡大していく. また,データベースへの負荷が増減したときのスケーリングは, DynamoDB が自動で行うので,ユーザーは心配する必要はない.

    DynamoDB での利用料金の計算はやや複雑なのだが, "On-demand Capacity" というモードで使用した場合の料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 詳細は 公式ドキュメンテーション "Pricing for On-Demand Capacity" を参照).

    DynamoDB の利用料金
    項目料金

    Write request units

    $1.25 per million write request units

    Read request units

    $0.25 per million read request units

    Data storage

    $0.25 per GB-month

    DynamoDB ではデータの書き込み操作の単位を write request unit とよび,データの読み込み操作の単位を read request unit とよぶ. 基本的に, 1kB 以下のデータを一度書き込むと 1 write request unit を消費し,4kB 以下のデータを一度読み込むと 1 read request unit を消費する (詳しくは 公式ドキュメンテーション "Read/Write Capacity Mode" を参照のこと). write request units は 100 万回ごとに $1.25, read request units は 100 万回ごとに $0.25 のコストが設定されている. また,保存されたデータ容量に対して $0.25 per GB のコストが月ごとに発生する. DynamoDB は高速な検索機能などを備えたデータベースであるので, GB あたりのストレージコストは S3 に比べ 10 倍程度高い. DynamoDB のデータの転送に関わるコストは,同じリージョン内ならば data-in,data-out ともに $0 である. リージョンをまたいだ通信には別途コストが発生する.

    その他のサーバーレスクラウドの構成要素

    以上で紹介した Lambda, S3, DynamoDB がサーバーレスクラウドの中で最も使用する頻度が高いサービスになる. その他のサーバーレスクラウドの構成要素を以下に列挙する. いくつかについては,今後のハンズオンを行う中で改めて解説を行う.

    サーバーレスアーキテクチャは万能か?

    この問いへの答えは,筆者は NO であると考える.

    ここまで,サーバーレスの利点を強調して説明をしてきたが,まだまだ新しい技術なだけに,欠点,あるいはサーバーフルなシステムに劣る点は数多くある.

    大きな欠点を一つあげるとすれば,サーバーレスのシステムは各クラウドプラットフォームに固有なものなので,特定のプラットフォームでしか運用できないシステムになってしまう点であろう. AWS で作成したサーバーレスのシステムを, Google のクラウドに移植するには,かなり大掛かりなプログラムの書き換えが必要になる. 一方, serverful なシステムであれば,プラットフォーム間のマイグレーションは比較的簡単に行うことができる. クラウドプロバイダーとしては,自社のシステムへの依存度を強めることで,顧客を離さないようにするという狙いがあるのだろう…

    その他,サーバーレスコンピューティングの欠点や今後の課題などは,次の論文で詳しく議論されている. 興味のある読者はぜひ読んでいただきたい.

    Hands-on #5: サーバーレス入門

    前章ではサーバーレスアーキテクチャの概要の説明を行った. 本章では,ハンズオン形式でサーバーレスクラウドを実際に動かしながら,具体的な使用方法を学んでいこう. 今回のハンズオンでは Lambda, S3, DynamoDB の三つのサーバーレスクラウドの構成要素に触れていく. それぞれについて,短いチュートリアルを用意してある.

    Lambda ハンズオン

    まずは, Lambda を実際に動かしてみよう. ハンズオンのソースコードは GitHub の handson/serverless/lambda に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して Python で書かれたコードを Lambda に登録する. 続いて STEP 2 では, Invoke API を使用して,同時にいくつもの Lambda を起動し,並列な計算を行う. Lambda のワークフローを体験する目的で最小限の設定である.

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    py
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
    +
    +class SimpleLambda(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
    +
    +class SimpleLambda(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

    • 次に, Lambda に <1> で書いた関数を配置している. パラメータの意味は,文字どおりの意味なので難しくはないが,以下に解説する.

      • runtime=_lambda.Runtime.PYTHON_3_7: ここでは, Python3.7 を使って上記で定義された関数を実行せよ,と指定している. Python3.7 のほかに, Node.js, Java, Ruby, Go などの言語を指定することが可能である.

      • code=_lambda.Code.from_inline(FUNC): 実行されるべき関数が書かれたコードを指定する. ここでは, FUNC=... で定義した文字列を渡しているが,文字列以外にもファイルのパスを渡すことも可能である.

      • handler="index.handler": これは,コードの中にいくつかのサブ関数が含まれているときに,メインとサブを区別するためのパラメータである. handler という名前の関数をメイン関数として実行せよ,という意味である.

      • memory_size=128: メモリーは 128MB を最大で使用することを指定している.

      • timeout=core.Duration.seconds(10) タイムアウト時間を 10 秒に設定している. 10 秒以内に関数の実行が終了しなかった場合,エラーが返される.

      • dead_letter_queue_enabled=True: アドバンストな設定なので説明は省略する.

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    Lambda コンソール - 関数の一覧

    今回のアプリケーションで作成したのが SimpleLambda で始まるランダムな名前のついた関数だ. 関数の名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. 先ほどプログラムの中で定義した Python の関数がエディターから確認できる. さらに下の方にスクロールすると,関数の各種設定も確認できる.

    Lambda コンソール - 関数の詳細

    Lambda で実行されるコードは, Lambda のコンソール画面 (figure_title) のエディターで編集することもできる. デバッグをするときなどは,こちらを直接いじる方が早い場合もある. その場合は, CDK のコードに行った編集を反映させなおすことを忘れずに.

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    sh
    ....................................................................................................
    +Submitted 100 tasks to Lambda!
    ....................................................................................................
    +Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    figure_title で "Invocations" が関数が何度実行されたかを意味している. たしかに 100 回実行されていることがわかる. さらに, "Concurrent executions" は何個のタスクが同時に行われたかを示している. ここでは 96 となっていることから,96 個のタスクが並列的に実行されたことを意味している (これが 100 とならないのは,タスクの開始のコマンドが送られたのが完全には同タイミングではないことに起因する).

    このように,非常にシンプルではあるが, Lambda を使うことで,同時並列的に処理を実行することのできるクラウドシステムを簡単に作ることができた.

    もしこのようなことを従来的な serverful なクラウドで行おうとした場合,クラスターのスケーリングなど多くのコードを書くことに加えて,いろいろなパラメータを調節する必要がある.

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • partition_key: すべての DynamoDB テーブルには Partition key が定義されていなければならない. Partition key とは,テーブル内の要素 (レコード) ごとに存在する固有の ID のことである. 同一の Partition key をもった要素がテーブルの中に二つ以上存在することはできない (注: Sort Key を使用している場合は除く.詳しくは 公式ドキュメンテーション "Core Components of Amazon DynamoDB" 参照). また, Partition key が定義されていない要素はテーブルの中に存在することはできない. ここでは, Partition key に item_id という名前をつけている.

    • billing_mode: ddb.BillingMode.PAY_PER_REQUEST を指定することで, On-demand Capacity Mode の DynamoDB が作成される. ほかに PROVISIONED というモードがあるが,これはかなり高度なケースを除いて使用しないだろう.

    • removal_policy: CloudFormation のスタックが消去されたときに, DynamoDB も一緒に消去されるかどうかを指定する. このコードでは DESTROY を選んでいるので,すべて消去される. ほかのオプションを選択すると,スタックを消去しても DynamoDB のバックアップを残す,などの動作を定義することができる.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    DynamoDB のコンソール (テーブルの一覧)

    今回のアプリケーションで作成したのが SimpleDynamoDb で始まるランダムな名前のついたテーブルだ. テーブルの名前をクリックして,詳細を見てみる. すると figure_title のような画面が表示されるはずだ. "Items" のタブをクリックすると,テーブルの中のレコードを確認できる. 現時点ではなにもデータを書き込んでいないので,空である.

    DynamoDB のコンソール (テーブルの詳細画面)

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    python
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
    +
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
    +
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    python
    import boto3
    +ddb = boto3.resource('dynamodb')
    +
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)
    import boto3
    +ddb = boto3.resource('dynamodb')
    +
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    python
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    python
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if key is None:
    +        key = os.path.basename(filename)
    +
    +    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if key is None:
    +        key = os.path.basename(filename)
    +
    +    bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    python
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if filename is None:
    +        filename = os.path.basename(key)
    +
    +    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
    +
    +    if filename is None:
    +        filename = os.path.basename(key)
    +
    +    bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #6: Bashoutter

    さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

    ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

    準備

    ハンズオンのソースコードは GitHub の handson/bashoutter に置いてある.

    本ハンズオンの実行には,第一回ハンズオンで説明した準備 (準備) が整っていることを前提とする. それ以外に必要な準備はない.

    このハンズオンは,基本的に AWS の無料枠 の範囲内で実行できる.

    アプリケーションの説明

    API

    今回のアプリケーションでは,人々からの俳句の投稿を受け付けたり,投稿された俳句の一覧を取得する,といった機能を実装したい. この機能を実現するための最小限の設計として, table_title に示すような四つの REST API を今回は実装する. 俳句を投稿する,閲覧する,削除するという基本的なデータ操作を行うための API が完備されている. また, PATCH /haiku/{item_id} は, {item_id} で指定された俳句に”いいね”をするために使用する.

    Bashoutter API

    GET /haiku

    俳句の一覧を取得する

    POST /haiku

    新しい俳句を投稿する

    PATCH /haiku/{item_id}

    {item_id} で指定された俳句にお気に入り票を一つ入れる

    DELETE /haiku/{item_id}

    {item_id} で指定された俳句を削除する

    それぞれの API のパラメータおよび返り値の詳細は,ハンズオンのソースコードの中の swagger.yml に定義してある.

    Open API Specification (OAS; 少し前は Swagger Specification とよばれていた) は, REST API のための記述フォーマットである. OAS に従って API の仕様が記述されていると,簡単にドキュメンテーションを生成したり,クライアントアプリケーションを自動生成することができる. 今回用意した API 仕様 も, OAS に従って書いてある. 詳しくは Swagger の公式ドキュメンテーション などを参照.

    アプリケーションアーキテクチャ

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#5で作製するアプリケーションのアーキテクチャ

    簡単にまとめると,次のような設計である.

    • クライアントからの API リクエストは, API Gateway (後述)にまず送信され, API の URI で指定された Lambda 関数へ転送される.

    • それぞれの API のパス (リソース) ごとに独立した Lambda を用意する.

    • 俳句の情報 (作者,本文,投稿日時など) を記録するためのデータベース (DynamoDB) を用意する.

    • 各 Lambda 関数には, DynamoDB へのアクセス権を付与する.

    • 最後に,ウェブブラウザからコンテンツを表示できるよう, ウェブページの静的コンテンツを配信するための S3 バケットを用意する.クライアントはこの S3 バケットにアクセスすることで HTML/CSS/JS などのコンテンツを取得する.

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    python
    class Bashoutter(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
    +
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
    +
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
    +
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
    +
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
    +
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    class Bashoutter(core.Stack):
    +
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
    +
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    +
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
    +
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
    +
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
    +
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
    +
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
    +
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

    • 静的コンテンツを配信するための S3 バケットを用意している.

    • それぞれの API で実行される Lambda 関数を定義している. 関数は Python3.7 で書かれており,コードは handson/bashoutter/api/api.py にある.

    • <3> で定義された Lambda 関数に対し,データベースへの読み書きのアクセス権限を付与している.

    • ここで,API Gateway により,各 API パスとそこで実行されるべき Lambda 関数を紐付けている.

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    python
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    今回のハンズオンでは説明の簡略化のため CloudFront の設定を行わなかったが,興味のある読者は次のリンクのプログラムが参考になるだろう.

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    python
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    python
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
    +
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
    +
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
    +
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
    +
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    python
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    そのような理由により,このコードでは GET のハンドラー関数に対しては grant_read_data() によって, read 権限のみを付与している.

    API Gateway

    API Gateway とは, API の"入り口"として,API のリクエストパスに従って Lambda や EC2 などに接続を行うという機能を担う (figure_title). Lambda や EC2 によって行われた処理の結果は,再び API Gateway を経由してクライアントに返される. このように,クライアントとバックエンドサーバーの間に立ち, API のリソースパスに応じて接続先を振り分けるようなサーバーをルーター,あるいはリバースプロキシとよんだりする. 従来的には,ルーターにはそれ専用の仮想サーバーが置かれることが一般的であった. しかし, API Gateway はサーバーレスなルーターとして,固定されたサーバーを配置することなく, API のリクエストが来たときのみ起動し,API のルーティングを実行する. サーバーレスであることの当然の帰結として,アクセスの件数が増大したときにはそれにルーティングの処理能力を自動で増やす機能も備わっている.

    API Gateway

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    python
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
    +
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
    +
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
    +
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
    +
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

    • 次に, api.root.add_resource() のメソッドを呼ぶことで, /haiku という API パスを追加している.

    • 続いて, add_method() を呼ぶことで, GET, POST のメソッドを /haiku のパスに定義している.

    • さらに, haiku.add_resource("{item_id}") により, /haiku/{item_id} という API パスを追加している.

    • 最後に, add_method() を呼ぶことにより, PATCH, DELETE のメソッドを /haiku/{item_id} のパスに定義している.

    このように, API Gateway の使い方は非常にシンプルで,逐次的に API パスとそこで実行されるメソッド・Lambda を記述していくだけでよい.

    このプログラムで 新規 API を作成すると, ランダムな URL がその API のエンドポイントとして割り当てられる. これを. api.example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    sh
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
    +
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    +
    +# デプロイを実行
    +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    API Gateway コンソール画面 (1)

    今回デプロイした "BashoutterApi" という名前の API をクリックすることで figure_title のような画面に遷移し,詳細情報を閲覧できる. GET /haiku, POST /haiku などが定義されていることが確認できる.

    それぞれのメソッドをクリックすると,そのメソッドの詳細情報を確認できる. API Gateway は,前述したルーティングの機能だけでなく,認証機能などを追加することも可能である. このハンズオンではとくにこれらの機能は使用しないが, "Method Request" と書いてある項目などがそれに相当する. 次に, figure_title で画面右端の赤色で囲った部分に,この API で呼ばれる Lambda 関数が指定されていることに注目しよう. 関数名をクリックと,該当する Lambda のコンソールに遷移し,関数の中身を閲覧することが可能である.

    API Gateway コンソール画面 (2)

    次に, S3 のコンソール画面に移ってみよう. bashouter- で始まるランダムな名前のバケットが見つかるはずである (figure_title).

    S3 コンソール画面

    バケットの名前をクリックすることで,バケットの中身を確認してみよう. index.html のほか, css/, js/ などのディレクトリがあるのが確認できるだろう (figure_title). これらが,ウェブページの"枠"を定義している静的コンテンツである.

    S3 バケットの中身

    API リクエストを送信する

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"

    次のような出力が得られるだろう.

    sh
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
    +
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている (figure_title 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    ウェブブラウザを開き,アドレスバーに S3 の URL を入力しへアクセスしてみよう. すると, figure_title のようなページが表示されるはずである.

    "Bashoutter" の GUI 画面

    ページが表示されたら,一番上の "API Endpoint URL" と書いてあるテキストボックスに,今回デプロイした API Gateway の URL を入力する (今回のアプリケーションでは,API Gateway の URL はランダムに割り当てられるのでこのような GUI の仕様になっている). そうしたら,画面の "REFRESH" と書いてあるボタンを押してみよう. データベースに俳句が登録済みであれば,俳句の一覧が表示されるはずである. 各俳句の左下にあるハートのアイコンをクリックすることで, "like" の票を入れることができる.

    新しい俳句を投稿するには,五七五と投稿者の名前を入力して, "POST" を押す. "POST" を押した後は,再び "REFRESH" ボタンを押すことで最新の俳句のリストをデータベースから取得する.

    アプリケーションの削除

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. Hands-on #5: サーバーレス入門 では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    これらの演習を通じて,世の中のウェブサービスがどのようにしてでき上がっているのか,少し理解が深まっただろうか? また,そのようなウェブアプリケーションを自分が作りたいと思ったとき,今回のハンズオンがその出発点となることができたならば幸いである.

    まとめ

    Appendix: 環境構築

    本書を読み進めるにあたって,ハンズオンのプログラムを実行するための環境を自分のローカルマシンにセットアップしなければならない. ここでは, AWS やコマンドラインの初心者を想定して,本章で必要なソフトウェアやライブラリのインストールなどを簡単に解説する. 以下に簡単な目次を示そう. 既に環境構築が済んでいる場合は適宜読み飛ばしていただき,関係のある箇所のみ目を通せば良い.

    使用する OS は Linux/Mac/Windows のどれを用いても構わない. Windows のユーザーは, Windows Subsytem for Linux (WSL) を使用することを想定している (WSL のインストール).

    また,本書のハンズオンを実行するための Docker イメージ を提供している. これを用いると, AWS CLI/CDK や Python の設定などをスキップできるので, Docker の使用方法を知っている読者には便利だろう.

    AWS アカウントの取得

    本書で提供するハンズオンを実際に自分で試すには,読者自身で AWS のアカウントの作成をする必要がある. 詳しいアカウントの作成の手順は 公式のドキュメンテーション に書かれているので,そちらも参照していただきたい. 以下の手順に従ってアカウントの作成を行う.

    まず,ウェブブラウザから AWS コンソール にアクセスし,右上の Create an AWS Account をクリックする (figure_title で実線で囲った部分).

    サインアップ (1): AWS コンソールにアクセス

    次に,遷移した先のページでメールアドレスとパスワードなどの登録を行う (figure_title).

    サインアップ (2): メールアドレス・パスワードなどの登録.

    続いて,住所や電話番号などを訊かれるので,すべて入力しよう (figure_title).

    サインアップ (3): 住所・電話番号の入力

    次に,クレジットカードの情報の登録を求められる (figure_title). 個人で AWS を利用する場合は,利用料金の請求はクレジットカードを経由して行われる. クレジットカードの登録なしには AWS を使い始めることはできないことに注意.

    サインアップ (4): クレジットカードの登録

    次の画面では,携帯電話の SMS またはボイスメッセージを利用した本人確認が求められる (figure_title). 希望の認証方法を選択し,自分の携帯電話番号を入力しよう.

    サインアップ (5): 携帯電話による本人確認

    無事に本人確認が完了すると,最後にサポートプランの選択を求められる (figure_title). 無料の Basic support を選択しておけば問題ない.

    サインアップ (6): サポートプランの選択

    以上のステップにより,アカウントの作成が完了する (figure_title). 早速ログインをして, AWS コンソールにアクセスできるか確認しておこう.

    サインアップ (7): アカウントの作成が完了した

    AWS のシークレットキーの作成

    AWS シークレットキーとは, AWS CLI や AWS CDK から AWS の API を操作するときに,ユーザー認証を行うための鍵のことである. AWS CLI/CDK を使うには,最初にシークレットキーを発行する必要がある. AWS シークレットキーの詳細は 公式ドキュメンテーション "Understanding and getting your AWS credentials" を参照.

    1. AWS コンソールにログインする.

    2. 画面右上のアカウント名をクリックし,表示されるプルダウンメニューから "My Security Credentials" を選択 (figure_title)

    3. "Access keys for CLI, SDK, & API access" の下にある "Create accesss key" のボタンをクリックする (figure_title)

    4. 表示された Access key ID, Secret access key を記録しておく (画面を閉じると二度と表示されない).

    5. 鍵を忘れてしまった場合などは,同じ手順で再発行が可能である.

    6. 発行したシークレットキーは, ~/.aws/credentials のファイルに書き込むか,環境変数に設定するなどして使う (詳しくは AWS CLI のインストール).

    AWS シークレットキーの発行1

    AWS シークレットキーの発行2

    AWS Educate Starter Account を用いている場合は,次の手順でシークレットキーを確認する.

    • AWS Educate のコンソール画面から, vocareum のコンソールに移動する (figure_title).

    • Account Details をクリックし,続いて AWS CLI: Show をクリックする.

    • aws_access_key_id, aws_secret_access_key, aws_session_token が表示される (figure_title). ここで表示された内容を ~/.aws/credentials にコピーする (AWS CLI のインストール 参照). aws_session_token の箇所も漏らさずコピーすること.

    • 続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

      [default] region = us-east-1 output = json

    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).

    vocareum コンソール

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    sh
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    本書のハンズオンではコマンドラインから AWS CLI のコマンドを実行したり, Python で書かれたプログラムを実行する. コマンドは基本的に UNIX のターミナルを想定して書かれている. Linux や Mac のユーザーは OS に標準搭載されているターミナルを用いれば良い. Windows を利用している読者は, Windows Subsystem for Linux (WSL) を利用することで,仮想の Linux 環境を構築することを推奨する. Cygwin などの Linux 環境をエミュレートするほかのツールでも構わないが,本書のプログラムは WSL でのみ動作確認を行っている.

    WSL とは, Windows の OS 上で Linux の仮想環境を起動するための, Microsoft 社が公式で提供しているソフトウェアである. Ubuntu など希望の Linux distribution が選択でき,基本的にすべての Linux 向けに作られたプログラム・ソフトウェアを使用することができる.

    執筆時点では WSL 2 が最新版として提供されているので,以下では WSL 2 のインストール手順を簡単に説明する. 細かな詳細などは, 公式ドキュメンテーション を参照のこと.

    前提として,使用される OS は Windows 10 (Pro または Home エディション) でなければならない. さらに,使用している Windows 10 のバージョンが WSL に対応するバージョンであるかを確認する. X64 のシステムでは Version 1903, Build 18362 以上でなければならない. バージョンが対応していない場合は、 Windows のアップデートを行う.

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    powersh
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    sh
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    Ubuntu 20.04 を初回に起動すると,初期設定が自動で開始され,数分待つことになる. 初期設定が終わると,ユーザー名・パスワードを設定するようプロンプトが出るので,プロンプトに従い入力する.

    これで WSL2 のインストールが完了した. 早速 WSL2 を起動してみよう. 左下の Windows メニューの検索バーに Ubuntu と入力すると, Ubuntu 20.04 のプログラムが見つかるはずである (figure_title). クリックして起動しよう.

    Ubuntu 20.04 の起動

    すると,ターミナルの黒い画面が立ち上がるだろう (figure_title). ls, top などのコマンドを打ってみて, WSL がきちんと動作していることを確認しよう.

    WSL の起動画面

    オプションとして, Windows Terminal というマイクロソフトから提供されているツールを使うと,より快適に WSL を使用することができる. 興味のある読者はこちらのインストールも推奨する.

    Docker のインストール

    Docker のインストールの方法は OS によって異なる.

    Mac ユーザーは, Docker Desktop をインストールする. インストールの方法は, Docker のウェブサイト から, Mac 版の Docker Desktop をダウンロードし,ダウンロードされたファイルをダブルクリックし, Applications のフォルダにドラッグするだけで良い. 詳細は 公式ドキュメンテーション を参照のこと.

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    ハンズオンを実行するために必要な, Node.js, Python, AWS CDK などがインストールされた Docker image を用意した. これを使用することで,自分のローカルマシンに諸々をインストールする必要なく,すぐにハンズオンのコードが実行できる.

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    sh
    root@aws-handson:~/programlisting
    root@aws-handson:~/programlisting

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい (プログラムを実行する など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    ライセンス

    本教科書およびハンズオンのソースコードは CC BY-NC-ND 4.0 に従うライセンスで公開しています.

    教育など非商用の目的での本教科書の使用や再配布は自由に行うことが可能です. 商用目的で本書の全体またはその一部を無断で転載する行為は,これを固く禁じます.

    + \ No newline at end of file diff --git a/development/aws/scientific-computing.html b/development/aws/scientific-computing.html index 7c46b004..fe8e6947 100644 --- a/development/aws/scientific-computing.html +++ b/development/aws/scientific-computing.html @@ -5,16 +5,16 @@ クラウドで行う科学計算・機械学習 | Toshiki's Note - + - + - + - + @@ -37,8 +37,8 @@ -
    Skip to content

    クラウドで行う科学計算・機械学習

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:1.4k
    Reading:5 min

    計算機が発達した現代では,計算機によるシミュレーションやビッグデータの解析は,科学・エンジニアリングの研究の主要な柱である. これらの大規模な計算を実行するには,クラウドは最適である. 本章から始まる第二部では,どのようにしてクラウド上で科学計算を実行するのかを,ハンズオンとともに体験してもらう. 科学計算の具体的な題材として,今回は機械学習(深層学習)を取り上げる.

    なお,本書では PyTorch ライブラリを使って深層学習のアルゴリズムを実装するが,深層学習および PyTorch の知識は不要である. 講義ではなぜ・どうやって深層学習をクラウドで実行するかに主眼を置いているので,実行するプログラムの詳細には立ち入らない. 将来,自分で深層学習を使う機会が来たときに,詳しく学んでもらいたい.

    なぜ機械学習をクラウドで行うのか?

    2010 年頃に始まった第三次 AI ブームのおかげで,学術研究だけでなく社会・ビジネスの文脈でも機械学習に高い関心が寄せられている. とくに,深層学習 (ディープラーニング) とよばれる多層のレイヤーからなるニューラルネットワークを用いたアルゴリズムは,画像認識や自然言語処理などの分野で圧倒的に高い性能を実現し,革命をもたらしている.

    深層学習の特徴は,なんといってもそのパラメータの多さである. 層が深くなるほど,層間のニューロンを結ぶ重みパラメータの数が増大していく. たとえば,最新の言語モデルである GPT-3 には1750 億個ものパラメータが含まれている. このような膨大なパラメータを有することで,深層学習は高い表現力と汎化性能を実現しているのである.

    GPT-3 に限らず,最近の SOTA (State-of-the-art) の性能を達成するニューラルネットワークでは,百万から億のオーダーのパラメータを内包することは頻繁になってきている. そのような巨大なニューラルネットを訓練 (最適化) させるのは,当然のことながら膨大な計算コストがかかる. 結果として,ひとつの計算機では丸一日以上の時間がかかる場合も珍しくない. 深層学習の発展の速度は目覚ましく,研究・ビジネス両方の観点からも,いかにスループットよくニューラルネットワークの最適化を行えるかが鍵となってくる. そのような問題を解決するのにとても有効な手段が,クラウドである! (#sec_first_ec2) でその片鱗を見たように,クラウドを使用することでゼロから数千に至るまでの数のインスタンスを動的に起動し,並列に計算を実行することができる. さらに,深層学習を加速させる目的で,深層学習の演算に専用設計された計算チップ (GPU など) がある. クラウドを利用すると,そのような専用計算チップも無尽蔵に利用することができる. 事実,先述した GPT-3 の学習も,詳細は明かされていないが,Microsoft 社のクラウドを使って行われたと報告されている.

    GPU による深層学習の高速化

    深層学習の計算で欠かすことのできない技術として, GPU (Graphics Processing Unit) について少し説明する.

    GPU は,その名のとおり,元々はコンピュータグラフィックスを出力するための専用計算チップである. CPU (Central Processing Unit) に対し,グラフィックスの演算に特化した設計がなされている. 身近なところでは, XBox や PS5 などのゲームコンソールなどに搭載されているし,ハイエンドなノート型・デスクトップ型計算機にも搭載されていることがある. コンピュータグラフィックスでは,スクリーンにアレイ状に並んだ数百万個の画素をビデオレート (30 fps) 以上で処理する必要がある. そのため,GPU はコアあたりの演算能力は比較的小さいかわりに,チップあたり数百から数千のコアを搭載しており (figure_title),スクリーンの画素を並列的に処理することで,リアルタイムでの描画を実現している.

    GPUのアーキテクチャ.GPUには数百から数千の独立した計算コアが搭載されている. (画像出典: https://devblogs.nvidia.com/nvidia-turing-architecture-in-depth/)

    このように,コンピュータグラフィクスの目的で生まれた GPU だが,2010 年前後から,その高い並列計算能力をグラフィックス以外の計算 (科学計算など) に用いるという流れ (General-purpose computing on GPU; GPGPU) が生まれた. GPU のコアは,その設計から,行列の計算など,単純かつ規則的な演算が得意であり,そのような演算に対しては数個程度のコアしかもたない CPU に比べて圧倒的に高い計算速度を実現することができる. 現在では GPGPU は分子動力学や気象シミュレーション,そして機械学習など多くの分野で使われている.

    ディープラーニングで最も頻繁に起こる演算が,ニューロンの出力を次の層のニューロンに伝える畳み込み (Convolution) 演算である (figure_title). 畳み込み演算は,まさに GPU が得意とする演算であり, CPU ではなく GPU を用いることで学習を飛躍的に (最大で数百倍程度) 加速させることができる.

    ニューラルネットワークにおける畳み込み演算.

    このように GPU は機械学習の計算で欠かせないものであるが,なかなか高価である. たとえば,科学計算・機械学習に専用設計された NVIDIA 社の Tesla V100 というチップは,一台で約百万円の価格が設定されている. 機械学習を始めるのに,いきなり百万円の投資はなかなか大きい. だが,クラウドを使えば,初期コスト0で GPU を使用することができる.

    機械学習を行うのに, V100 が必ずしも必要というわけではない. むしろ,研究者などでしばしば行われるのは,コンピュータゲームに使われるグラフィックス用の GPU を買ってきて (NVIDIA GeForce シリーズなど),開発のときはをそれを用いる,というアプローチである. グラフィックス用のいわゆる"コンシューマ GPU"は,市場の需要が大きいおかげで,10 万円前後の価格で購入することができる. V100 と比べると,コンシューマ GPU はコアの数が少なかったり,メモリーが小さかったりなどで劣る点があるが, それらを除いては計算能力にとくに制限があるわけではなく,開発の段階では十分な性能である場合がほとんどである. プログラムができあがって,ビッグデータの解析や,モデルをさらに大きくしたいときなどに,クラウドは有効だろう.

    クラウドで GPU を使うには, GPU が搭載された EC2 インスタンスタイプ (P3, P2, G3, G4 など) を選択しなければならない. table_title に,代表的な GPU 搭載のインスタンスタイプを挙げる (執筆時点での情報).

    GPUを搭載したEC2インスタンスタイプ
    InstanceGPUsGPU modelGPU Mem (GiB)vCPUMem (GiB)Price per hour ($)

    p3.2xlarge

    1

    NVIDIA V100

    16

    8

    61

    3.06

    p3n.16xlarge

    8

    NVIDIA V100

    128

    64

    488

    24.48

    p2.xlarge

    1

    NVIDIA K80

    12

    4

    61

    0.9

    g4dn.xlarge

    1

    NVIDIA T4

    16

    4

    16

    0.526

    table_title からわかるとおり, CPU のみのインスタンスと比べると少し高い価格設定になっている. また,古い世代の GPU (V100 に対しての K80) はより安価な価格で提供されている. 1 インスタンスあたりの GPU の搭載数は 1 台から最大で 8 台まで選択することが可能である.

    GPU を搭載した一番安いインスタンスタイプは, g4dn.xlarge であり,これには廉価かつ省エネルギー設計の NVIDIA T4 が搭載されている. 後のハンズオンでは,このインスタンスを使用して,ディープラーニングの計算を行ってみる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    V100 を一台搭載した p3.2xlarge の利用料金は一時間あたり $3.06 である. V100 が約百万円で売られていることを考えると,約 3000 時間 (= 124 日間),通算で計算を行った場合に,クラウドを使うよりも V100 を自分で買ったほうがお得になる,という計算になる (実際には,自前で V100 を用意する場合は, V100 だけでなく, CPU やネットワーク機器,電気使用料も必要なので,百万円よりもさらにコストがかかる).

    GPT-3 で使われた計算リソースの詳細は論文でも明かされていないのだが, Lambda 社のブログで興味深い考察が行われている (Lambda 社は機械学習に特化したクラウドサービスを提供している).

    記事によると,1750 億のパラメータを訓練するには,一台の GPU (NVIDIA V100) を用いた場合,342 年の月日と 460 万ドルのクラウド利用料が必要となる,とのことである. GPT-3 のチームは,複数の GPU に処理を分散することで現実的な時間のうちに訓練を完了させたのであろうが,このレベルのモデルになってくるとクラウド技術の限界を攻めないと達成できないことは確かである.

    深層学習を詳しく勉強したい人には以下の参考書を推薦したい. 深層学習の基礎的な概念や理論は普遍的であるが,この分野は日進月歩なので,常に最新の情報を取り入れることを忘れずに.

    - +
    Skip to content

    クラウドで行う科学計算・機械学習

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:1.4k
    Reading:5 min

    計算機が発達した現代では,計算機によるシミュレーションやビッグデータの解析は,科学・エンジニアリングの研究の主要な柱である. これらの大規模な計算を実行するには,クラウドは最適である. 本章から始まる第二部では,どのようにしてクラウド上で科学計算を実行するのかを,ハンズオンとともに体験してもらう. 科学計算の具体的な題材として,今回は機械学習(深層学習)を取り上げる.

    なお,本書では PyTorch ライブラリを使って深層学習のアルゴリズムを実装するが,深層学習および PyTorch の知識は不要である. 講義ではなぜ・どうやって深層学習をクラウドで実行するかに主眼を置いているので,実行するプログラムの詳細には立ち入らない. 将来,自分で深層学習を使う機会が来たときに,詳しく学んでもらいたい.

    なぜ機械学習をクラウドで行うのか?

    2010 年頃に始まった第三次 AI ブームのおかげで,学術研究だけでなく社会・ビジネスの文脈でも機械学習に高い関心が寄せられている. とくに,深層学習 (ディープラーニング) とよばれる多層のレイヤーからなるニューラルネットワークを用いたアルゴリズムは,画像認識や自然言語処理などの分野で圧倒的に高い性能を実現し,革命をもたらしている.

    深層学習の特徴は,なんといってもそのパラメータの多さである. 層が深くなるほど,層間のニューロンを結ぶ重みパラメータの数が増大していく. たとえば,最新の言語モデルである GPT-3 には1750 億個ものパラメータが含まれている. このような膨大なパラメータを有することで,深層学習は高い表現力と汎化性能を実現しているのである.

    GPT-3 に限らず,最近の SOTA (State-of-the-art) の性能を達成するニューラルネットワークでは,百万から億のオーダーのパラメータを内包することは頻繁になってきている. そのような巨大なニューラルネットを訓練 (最適化) させるのは,当然のことながら膨大な計算コストがかかる. 結果として,ひとつの計算機では丸一日以上の時間がかかる場合も珍しくない. 深層学習の発展の速度は目覚ましく,研究・ビジネス両方の観点からも,いかにスループットよくニューラルネットワークの最適化を行えるかが鍵となってくる. そのような問題を解決するのにとても有効な手段が,クラウドである! (#sec_first_ec2) でその片鱗を見たように,クラウドを使用することでゼロから数千に至るまでの数のインスタンスを動的に起動し,並列に計算を実行することができる. さらに,深層学習を加速させる目的で,深層学習の演算に専用設計された計算チップ (GPU など) がある. クラウドを利用すると,そのような専用計算チップも無尽蔵に利用することができる. 事実,先述した GPT-3 の学習も,詳細は明かされていないが,Microsoft 社のクラウドを使って行われたと報告されている.

    GPU による深層学習の高速化

    深層学習の計算で欠かすことのできない技術として, GPU (Graphics Processing Unit) について少し説明する.

    GPU は,その名のとおり,元々はコンピュータグラフィックスを出力するための専用計算チップである. CPU (Central Processing Unit) に対し,グラフィックスの演算に特化した設計がなされている. 身近なところでは, XBox や PS5 などのゲームコンソールなどに搭載されているし,ハイエンドなノート型・デスクトップ型計算機にも搭載されていることがある. コンピュータグラフィックスでは,スクリーンにアレイ状に並んだ数百万個の画素をビデオレート (30 fps) 以上で処理する必要がある. そのため,GPU はコアあたりの演算能力は比較的小さいかわりに,チップあたり数百から数千のコアを搭載しており (figure_title),スクリーンの画素を並列的に処理することで,リアルタイムでの描画を実現している.

    GPUのアーキテクチャ.GPUには数百から数千の独立した計算コアが搭載されている. (画像出典: https://devblogs.nvidia.com/nvidia-turing-architecture-in-depth/)

    このように,コンピュータグラフィクスの目的で生まれた GPU だが,2010 年前後から,その高い並列計算能力をグラフィックス以外の計算 (科学計算など) に用いるという流れ (General-purpose computing on GPU; GPGPU) が生まれた. GPU のコアは,その設計から,行列の計算など,単純かつ規則的な演算が得意であり,そのような演算に対しては数個程度のコアしかもたない CPU に比べて圧倒的に高い計算速度を実現することができる. 現在では GPGPU は分子動力学や気象シミュレーション,そして機械学習など多くの分野で使われている.

    ディープラーニングで最も頻繁に起こる演算が,ニューロンの出力を次の層のニューロンに伝える畳み込み (Convolution) 演算である (figure_title). 畳み込み演算は,まさに GPU が得意とする演算であり, CPU ではなく GPU を用いることで学習を飛躍的に (最大で数百倍程度) 加速させることができる.

    ニューラルネットワークにおける畳み込み演算.

    このように GPU は機械学習の計算で欠かせないものであるが,なかなか高価である. たとえば,科学計算・機械学習に専用設計された NVIDIA 社の Tesla V100 というチップは,一台で約百万円の価格が設定されている. 機械学習を始めるのに,いきなり百万円の投資はなかなか大きい. だが,クラウドを使えば,初期コスト0で GPU を使用することができる.

    機械学習を行うのに, V100 が必ずしも必要というわけではない. むしろ,研究者などでしばしば行われるのは,コンピュータゲームに使われるグラフィックス用の GPU を買ってきて (NVIDIA GeForce シリーズなど),開発のときはをそれを用いる,というアプローチである. グラフィックス用のいわゆる"コンシューマ GPU"は,市場の需要が大きいおかげで,10 万円前後の価格で購入することができる. V100 と比べると,コンシューマ GPU はコアの数が少なかったり,メモリーが小さかったりなどで劣る点があるが, それらを除いては計算能力にとくに制限があるわけではなく,開発の段階では十分な性能である場合がほとんどである. プログラムができあがって,ビッグデータの解析や,モデルをさらに大きくしたいときなどに,クラウドは有効だろう.

    クラウドで GPU を使うには, GPU が搭載された EC2 インスタンスタイプ (P3, P2, G3, G4 など) を選択しなければならない. table_title に,代表的な GPU 搭載のインスタンスタイプを挙げる (執筆時点での情報).

    GPUを搭載したEC2インスタンスタイプ
    InstanceGPUsGPU modelGPU Mem (GiB)vCPUMem (GiB)Price per hour ($)

    p3.2xlarge

    1

    NVIDIA V100

    16

    8

    61

    3.06

    p3n.16xlarge

    8

    NVIDIA V100

    128

    64

    488

    24.48

    p2.xlarge

    1

    NVIDIA K80

    12

    4

    61

    0.9

    g4dn.xlarge

    1

    NVIDIA T4

    16

    4

    16

    0.526

    table_title からわかるとおり, CPU のみのインスタンスと比べると少し高い価格設定になっている. また,古い世代の GPU (V100 に対しての K80) はより安価な価格で提供されている. 1 インスタンスあたりの GPU の搭載数は 1 台から最大で 8 台まで選択することが可能である.

    GPU を搭載した一番安いインスタンスタイプは, g4dn.xlarge であり,これには廉価かつ省エネルギー設計の NVIDIA T4 が搭載されている. 後のハンズオンでは,このインスタンスを使用して,ディープラーニングの計算を行ってみる.

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    V100 を一台搭載した p3.2xlarge の利用料金は一時間あたり $3.06 である. V100 が約百万円で売られていることを考えると,約 3000 時間 (= 124 日間),通算で計算を行った場合に,クラウドを使うよりも V100 を自分で買ったほうがお得になる,という計算になる (実際には,自前で V100 を用意する場合は, V100 だけでなく, CPU やネットワーク機器,電気使用料も必要なので,百万円よりもさらにコストがかかる).

    GPT-3 で使われた計算リソースの詳細は論文でも明かされていないのだが, Lambda 社のブログで興味深い考察が行われている (Lambda 社は機械学習に特化したクラウドサービスを提供している).

    記事によると,1750 億のパラメータを訓練するには,一台の GPU (NVIDIA V100) を用いた場合,342 年の月日と 460 万ドルのクラウド利用料が必要となる,とのことである. GPT-3 のチームは,複数の GPU に処理を分散することで現実的な時間のうちに訓練を完了させたのであろうが,このレベルのモデルになってくるとクラウド技術の限界を攻めないと達成できないことは確かである.

    深層学習を詳しく勉強したい人には以下の参考書を推薦したい. 深層学習の基礎的な概念や理論は普遍的であるが,この分野は日進月歩なので,常に最新の情報を取り入れることを忘れずに.

    + \ No newline at end of file diff --git a/development/aws/serverless.html b/development/aws/serverless.html index e2fe9921..8b2ccb9a 100644 --- a/development/aws/serverless.html +++ b/development/aws/serverless.html @@ -5,16 +5,16 @@ Serverless architecture | Toshiki's Note - + - + - + - + @@ -37,8 +37,8 @@ -
    Skip to content

    Serverless architecture

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:2.4k
    Reading:9 min

    サーバーレスアーキテクチャ (Serverless architecture) あるいは サーバーレスコンピューティング (Serverless computing) とは,従来とは全く異なるアプローチに基づくクラウドシステムの設計方法である. 歴史的には, AWS が 2014 年に発表した Lamba がサーバーレスアーキテクチャの先駆けとされている. その後, Google や Microsoft などのクラウドプラットフォームも同様の機能の提供を開始している. サーバーレスアーキテクチャの利点は,スケーラブルなクラウドシステムを安価かつ簡易に作成できる点であり,近年いたるところで導入が進んでいる.

    Serverless とは,文字どおりの意味としてはサーバーなしで計算をするということになるが,それは一体どういう意味だろうか? サーバーレスについて説明するためには,まずは従来的な, "serverful" とよばれるようなシステムについて解説しなければならない.

    Serverful クラウド (従来型)

    従来的なクラウドシステムのスケッチを figure_title に示す. クライアントから送信されたリクエストは,最初に API サーバーに送られる. API サーバーでは,リクエストの内容に応じてタスクが実行される. タスクには,API サーバーだけで完結できるものもあるが,多くの場合,データベースの読み書きが必要である. データベースには,データベース専用の独立したサーバーマシンが用いられることが一般的である. また,画像や動画などの容量の大きいデータは,また別のストレージサーバーに保存されることが多い. これらの API サーバー,データベースサーバー,ストレージサーバーはそれぞれ独立したサーバーマシンであり, AWS の言葉では EC2 による仮想インスタンスを想定してもらったらよい.

    多くのウェブサービスでは,多数のクライアントからのリクエストを処理するため,複数のサーバーマシンがクラウド内で起動し,負荷を分散するような設計がなされている. クライアントから来たリクエストを計算容量に余裕のあるサーバーに振り分けるような操作を Load balancing とよび,そのような操作を担当するマシンのことを Load balancer という.

    計算負荷を分散する目的で多数のインスタンスを起動するのはよいのだが,計算負荷が小さすぎてアイドリング状態にあるようではコストと電力の無駄遣いである. したがって,すべてのサーバーが常に目標とする計算負荷を維持するよう,計算の負荷に応じてクラスター内の仮想サーバーの数を動的に増減させるような仕組みが必要である. そのような仕組みをクラスターのスケーリングとよび,負荷の増大に応答して新しい仮想インスタンスをクラスターに追加する操作を scale-out,負荷の減少に応答してインスタンスをシャットダウンする操作を scale-in とよぶ. クラスターのスケーリングは, API サーバーではもちろんのこと,データベースサーバー・ストレージサーバーでも必要になる. ストレージサーバーでは,例えば頻繁にアクセスされるデータはキャッシュ領域に保存したり,データのコピーを複数作るなどのスケーリングが行われる. データベースサーバーも同様に,頻繁にアクセスされるデータのアクセスがパンクしてしまわないよう,分散的な処理が必要となる. このように,クラウドシステム内すべての箇所で,負荷が均一になるような調整が必要であり,開発者は多くの時間をそのチューニングに費やさなければならない. また,サービスの利用者の数などに応じてスケーリングの設定は常に見直される必要があり,継続的な開発が要求される.

    さらに問題を複雑にするのは,API サーバーで処理されるべきタスクが,非一様な点である. 非一様であるとは,たとえばタスク A は 3000 ミリ秒の実行時間と 512MB のメモリーを消費し,別のタスク B は 1000 ミリ秒の実行時間と 128MB のメモリーを消費する,というような状況を指している. 一つのサーバーマシンが計算負荷が異なる複数のタスクを処理する場合,クラスターのスケーリングはより複雑になる. この状況をシンプルにするために,1サーバーで実行するタスクは1種類に限る,という設計も可能であるが,そうするとで生まれる弊害も多い (ほとんど使われないタスクに対してもサーバー一台をまるまる割り当てなければならない = ほとんどアイドリング状態になってしまう,など).

    Serverful なクラウドシステム

    Serverless クラウドへ

    Serverful クラウド (従来型) で議論したように,クラスターのスケーリングはクラウドシステムの経済的効率とシステムの安定性を最大化するために必須の作業である. それを反映して,多くの開発者の時間が投資されてきた.

    クラスターのスケーリングはすべての開発者が何度も繰り返し行ってきた作業であり,いくつかの側面をテンプレート化し,共通化することができたならば開発のコストを大幅に削減できるだろう. それを実現するには,根本的なレベルからクラウドシステムの設計を考え直す必要がある. スケーリングを前提として考えることで,もっとシンプルで見通しがよいクラウドシステムの設計の仕組みはないだろうか? そのような動機が,サーバーレスアーキテクチャが誕生する背後にあった.

    従来の serverful なシステムでの最大の問題点は,サーバーをまるまる占有してしまうという点にある. すなわち, EC2 インスタンスを起動したとき,そのインスタンスは起動したユーザーだけが使えるものであり,計算のリソース (CPU や RAM) が独占的に割り当てられた状態になる. 固定した計算資源の割り当てがされてしまっているので,インスタンスの計算負荷が 0%であろうが 100%であろうが,均一の使用料金が起動時間に比例して発生する.

    サーバーレスアーキテクチャは,このような 独占的に割り当てられた計算リソースというものを完全に廃止することを出発点とする. サーバーレスアーキテクチャでは,計算のリソースは,クラウドプロバイダーがすべて管理する. クライアントは,仮想インスタンスを一台まるごと借りるのではなく,計算のタスクの需要が生まれる毎に,実行したいプログラム・コマンドをクラウドに提出する. クラウドプロバイダーは,自身のもつ巨大な計算リソースから空きを探し,提出されたプログラムを実行し,実行結果をクライアントに返す. 言い換えると,計算リソースのスケーリングやアロケーションなどはクラウドプロバイダーが一手に引き受け,ユーザーはジョブをサブミットすることに注力する,という枠組みである. これを図示すると, figure_title のようになる.

    従来のクラウドと Serverless クラウドの比較

    サーバーレスクラウドでは,スケーリングはすべてクラウドプロバイダーが引き受けるので,スケーラビリティーが保証されている. クライアントが同時に大量のタスクを送信した場合でも,クラウドプロバイダー側の独自の仕組みによってすべてのタスクが遅延なく実行される. また,サーバーレスクラウドを利用することで,クラウドのコストは実際に使用した計算の総量 (稼働時間) で決定されることになる. これは,計算の実行総量に関わらずインスタンスの起動時間で料金が決定されていた従来のシステムと比べて大きな違いである.

    サーバーレスクラウドは,従来のクラウドとは根本から異なったアプローチなので,コードの書き方やシステムの設計が大きく異なる. サーバーレスクラウドを開発・運用するには,サーバーレス固有の概念や用語に精通している必要がある. 以降では,実際にクラウドを動かしながら,サーバーレスをより具体的に体験していこう.

    従来型の(仮想インスタンスをたくさん起動するような)クラウドシステムは,賃貸と似ているかもしれない. 部屋を借りるというのは,その部屋でどれだけの時間を過ごそうが,月々の家賃は一定である. 同様に,仮想サーバーも,それがどれほどの計算を行っているかに関わらず,一定の料金が時間ごとに発生する.

    一方で,サーバーレスクラウドは,電気・水道・ガス料金 と似ている. こちらは,実際に使用した量に比例して料金が決定されている. サーバーレスクラウドも,実際に計算を行った総時間で料金が決まる仕組みになっている.

    サーバーレスクラウドを構成するコンポーネント

    サーバーレスアーキテクチャの概要がわかってきたところで,ここでは AWS においてサーバーレスクラウドを構成する様々なコンポーネントを紹介していこう. 特に, Lambda, S3, DynamoDB を取り上げ,解説する (figure_title). サーバーレスクラウドは,これらのコンポーネントを統合することで一つのシステムが出来上がる. ここでは, Lambda,S3,DynamoDB を利用する際に押さえておかなければならない知識を一通り説明しきる都合上,具体的なイメージがわきにくいかもしれない. が,続く (#sec_intro_serverless) でそれぞれについてハンズオン形式で演習を行うので,そこでさらに理解を深めれば大丈夫である.

    Lambda, S3, DynamoDB のアイコン

    Lambda

    AWS でサーバーレスコンピューティングの中心を担うのが, Lambda である. Lambda の使い方を figure_title に図示している. Lambda の仕組みはシンプルで,まずユーザーは実行したいプログラムのコードを事前に登録しておく. プログラムは, Python, Node.js, Ruby などの主要な言語がサポートされている. Lambda に登録されたひとつひとつのプログラムを関数 (Function) とよぶ. そして,関数を実行したいときに,invoke コマンドを Lambda に送信する. Lambda では, invoke のリクエストを受け取るとただちに (数ミリセカンドから数百ミリセカンド程度の時間で) プログラムの実行を開始する. そして,実行結果をクライアントやその他の計算機に返す.

    AWS Lambda

    このように,Lambda では占有された仮想インスタンスは存在せず,実行を待っているプログラムだけがある状態である. invoke のリクエストに応じて,プログラムが AWS の巨大な計算機プールのどこかに配置され,実行される. 同時に複数のリクエストが来た場合でも, AWS はそれらを実行するための計算リソースを割り当て,並列的に処理を行ってくれる. 原理上は,数千から数万のリクエストが同時に来たとしても, Lambda はそれらを同時に実行することができる. このような,占有された仮想サーバーの存在なしに,動的に関数を実行するサービスのことを総称して FaaS (Function as a Service) とよぶ.

    Lambda ではそれぞれの関数につき, 128MB から 10240MB のメモリーを使用することができる (執筆時点の仕様). また,実効的な CPU のパワーはメモリーの量に比例する形で割り当てられる. すなわち,タスクに割り当てたメモリーの量が多ければ多いほど,より多くの CPU リソースが割り当てられることになる (しかし, RAM と CPU パワーの具体的な換算表は AWS からは公開されていない). 実行時間は 100 ミリ秒の単位で記録され,実行時間に比例して料金が決定される. table_title は Lambda の利用料金表である (執筆時点で ap-north-east1 リージョンを選択した場合).

    Lambda の料金表
    Memory (MB)Price per 100ms

    128

    $0.0000002083

    512

    $0.0000008333

    1024

    $0.0000016667

    3008

    $0.0000048958

    実行時間に比例する料金に追加して,リクエストを送信するごとに発生する料金が設定されている. これは,百万回のリクエストにつき $0.2 である. たとえば, 128MB のメモリーを使用する関数を,それぞれ 200 ミリ秒,合計で 100 万回実行した場合, 0.0000002083 * 2 * 10^6 + 0.2 = $0.6 の料金となる. ウェブサーバーのデータベースの更新など簡単な計算であれば,200 ミリ秒程度で実行できる関数も多いことから,100 万回データベースの更新を行ったとしても,たった $0.6 しかコストが発生しないことになる. また,コードが実行されず待機状態になっている場合は,発生する料金は 0 である. このように,実際に意味のある処理が行われた時間にのみ,料金が発生する仕組みになっている.

    Lambda は比較的短時間で完了する,反復性の高いタスクの実行に向いている. データベースの読み書きはその典型的な例であるが,そのほかにも,画像のサイズをトリミングしたり,サーバーサイドで定期的に実行されるメンテナンス処理などの利用が考えられる. また,複数の Lambda をリレー式に繋げることも可能で,シンプルな処理を組み合わせることで複雑なロジックを表現することができる.

    上述の Lambda の料金計算は,説明のためコストに寄与する要素をいくつか省いている点は承知いただきたい. 例えば, DynamoDB の読み書きに関する料金や,ネットワークの通信にかかわるコストが考慮されていない.

    サーバーレスストレージ: S3

    サーバーレスの概念は,ストレージにも拡張されている.

    従来的なストレージ (ファイルシステム) では,必ずホストとなるマシンと OS が存在しなければならない. したがって,それほどパワーは必要ないまでも,ある程度の CPU リソースを割かなければならない. また,従来的なファイルシステムでは,データ領域のサイズは最初にディスクを初期化するときに決めなければならず,後から容量を増加させることはしばしば困難である (ZFS などのファイルシステムを使えばある程度は自由にファイルシステムのサイズを変更することは可能である). よって,従来的なクラウドでは,ストレージを借りる際にはあらかじめディスクのサイズを指定せねばならず,ディスクの中身が空であろうと満杯であろうと,同じ利用料金が発生することになる (figure_title).

    Simple Storage Service (S3) は,サーバーレスなストレージシステムを提供する (figure_title). S3 は従来的なストレージシステムと異なり, OS に"マウントする”という概念はない. 基本的に API を通じてデータの読み書きの操作が行われる. また,データの冗長化や暗号化,バックアップの作成など,通常ならば OS と CPU が介在しなければならない操作も, API を通じて行うことができる. S3 では事前に決められたディスク領域のサイズはなく,データを入れれば入れた分だけ,保存領域は拡大していく (仕様上はペタバイトスケールのデータを保存することが可能である). ストレージにかかる料金は,保存してあるデータの総容量で決定される.

    S3 と従来的なファイルシステムの比較

    S3 を利用する際に,料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 説明のため主要な事項のみ取り出している. 詳細は 公式ドキュメンテーション "Amazon S3 pricing" を参照).

    S3 の利用料金
    項目料金

    Data storage (First 50TB)

    $0.023 per GB per month

    PUT, COPY, POST, LIST requests (per 1,000 requests)

    $0.005

    GET, SELECT, and all other requests (per 1,000 requests)

    $0.0004

    Data Transfer IN To Amazon S3 From Internet

    $0

    Data Transfer OUT From Amazon S3 To Internet

    $0.09 per GB

    第一に,データの保存には $0.025 per GB のコストが月ごとに発生する. したがって,1000GB のデータを S3 に一ヵ月保存した場合, $25 の料金が発生することになる. また,PUT, COPY, POST などのリクエスト (=データを書き込む操作) に対しては,データ容量に関係なく,1000 回ごとに $0.005 のコストが発生する. GET, SELECT などのリクエスト (=データを読み込む操作) に対しては,1000 回ごとに $0.0004 のコストが発生する. また, S3 はデータを外に取り出す際の通信にもコストが生じる. 執筆時点では,S3 からインターネットを通じて外部にデータを転送 (data-out) すると $0.09 per GB のコストが発生する. データをインターネットを通じて S3 に入れる (data-in) 通信は無料で行える. また, AWS の 同じ Region 内のサービス (Lambda や EC2 など) にデータを転送するのは無料である. AWS のリージョンをまたいだデータの転送にはコストが発生する. いずれにせよ,サーバーレスの概念に則り,すべての料金が従量課金制で決定される設定になっている.

    サーバーレスデータベース: DynamoDB

    サーバーレスの概念は,データベースにも適用することができる.

    ここでいうデータベースとは, Web サービスなどにおけるユーザーや商品の情報を記録しておくための保存領域のことを指している. 従来的に有名なデータベースとしては MySQL, PostgreSQL, MongoDB などが挙げられる. データベースと普通のストレージの違いは,データの検索機能にある. 普通のストレージではデータは単純にディスクに書き込まれるだけだが, データベースでは検索がより効率的になるようなデータの配置がされたり, 頻繁にアクセスされるデータはメモリーにキャッシュされるなどの機能が備わっている. これにより,巨大なデータの中から,興味のある要素を高速に取得することができる.

    このような検索機能を実現するには,当然 CPU の存在が必須である. したがって,従来的なデータベースを構築する際は,ストレージ領域に加えて,たくさんの CPU コアを搭載したマシンが用いられることが多い. また,データベースが巨大な場合は複数マシンにまたがった分散型のシステムが設計される. 分散型システムの場合は, Serverful クラウド (従来型) で議論したようにデータベースへのアクセス負荷に応じて適切なスケーリングがなされる必要がある.

    DynamoDB は, AWS が提供しているサーバーレスな分散型データベースである. サーバーレスであるので,占有されたデータベース用仮想インスタンスは存在せず, API を通じてデータの書き込み・読み出し・検索などの操作を行う. S3 と同様に,データ保存領域の上限は定められておらず,データを入れれば入れた分だけ,保存領域は拡大していく. また,データベースへの負荷が増減したときのスケーリングは, DynamoDB が自動で行うので,ユーザーは心配する必要はない.

    DynamoDB での利用料金の計算はやや複雑なのだが, "On-demand Capacity" というモードで使用した場合の料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 詳細は 公式ドキュメンテーション "Pricing for On-Demand Capacity" を参照).

    DynamoDB の利用料金
    項目料金

    Write request units

    $1.25 per million write request units

    Read request units

    $0.25 per million read request units

    Data storage

    $0.25 per GB-month

    DynamoDB ではデータの書き込み操作の単位を write request unit とよび,データの読み込み操作の単位を read request unit とよぶ. 基本的に, 1kB 以下のデータを一度書き込むと 1 write request unit を消費し,4kB 以下のデータを一度読み込むと 1 read request unit を消費する (詳しくは 公式ドキュメンテーション "Read/Write Capacity Mode" を参照のこと). write request units は 100 万回ごとに $1.25, read request units は 100 万回ごとに $0.25 のコストが設定されている. また,保存されたデータ容量に対して $0.25 per GB のコストが月ごとに発生する. DynamoDB は高速な検索機能などを備えたデータベースであるので, GB あたりのストレージコストは S3 に比べ 10 倍程度高い. DynamoDB のデータの転送に関わるコストは,同じリージョン内ならば data-in,data-out ともに $0 である. リージョンをまたいだ通信には別途コストが発生する.

    その他のサーバーレスクラウドの構成要素

    以上で紹介した Lambda, S3, DynamoDB がサーバーレスクラウドの中で最も使用する頻度が高いサービスになる. その他のサーバーレスクラウドの構成要素を以下に列挙する. いくつかについては,今後のハンズオンを行う中で改めて解説を行う.

    • API Gateway: API を構築する際のルーティングを担う. (#sec_bashoutter) で取り上げる.

    • Fargate: (#sec_fargate_qabot) で触れた Fargate も,サーバーレスクラウドの要素の一部である. Lambda との違いは,Lambda よりも大容量のメモリーや CPU を要するような計算などを行うことができる点が挙げられる.

    • Simple Notification Service (SNS): サーバーレスのサービス間でイベントをやり取りするためのサービス.

    • Step Functions: サーバーレスのサービス間のオーケストレーションを担う.

    サーバーレスアーキテクチャは万能か?

    この問いへの答えは,筆者は NO であると考える.

    ここまで,サーバーレスの利点を強調して説明をしてきたが,まだまだ新しい技術なだけに,欠点,あるいはサーバーフルなシステムに劣る点は数多くある.

    大きな欠点を一つあげるとすれば,サーバーレスのシステムは各クラウドプラットフォームに固有なものなので,特定のプラットフォームでしか運用できないシステムになってしまう点であろう. AWS で作成したサーバーレスのシステムを, Google のクラウドに移植するには,かなり大掛かりなプログラムの書き換えが必要になる. 一方, serverful なシステムであれば,プラットフォーム間のマイグレーションは比較的簡単に行うことができる. クラウドプロバイダーとしては,自社のシステムへの依存度を強めることで,顧客を離さないようにするという狙いがあるのだろう…

    その他,サーバーレスコンピューティングの欠点や今後の課題などは,次の論文で詳しく議論されている. 興味のある読者はぜひ読んでいただきたい.

    - +
    Skip to content

    Serverless architecture

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:2.4k
    Reading:9 min

    サーバーレスアーキテクチャ (Serverless architecture) あるいは サーバーレスコンピューティング (Serverless computing) とは,従来とは全く異なるアプローチに基づくクラウドシステムの設計方法である. 歴史的には, AWS が 2014 年に発表した Lamba がサーバーレスアーキテクチャの先駆けとされている. その後, Google や Microsoft などのクラウドプラットフォームも同様の機能の提供を開始している. サーバーレスアーキテクチャの利点は,スケーラブルなクラウドシステムを安価かつ簡易に作成できる点であり,近年いたるところで導入が進んでいる.

    Serverless とは,文字どおりの意味としてはサーバーなしで計算をするということになるが,それは一体どういう意味だろうか? サーバーレスについて説明するためには,まずは従来的な, "serverful" とよばれるようなシステムについて解説しなければならない.

    Serverful クラウド (従来型)

    従来的なクラウドシステムのスケッチを figure_title に示す. クライアントから送信されたリクエストは,最初に API サーバーに送られる. API サーバーでは,リクエストの内容に応じてタスクが実行される. タスクには,API サーバーだけで完結できるものもあるが,多くの場合,データベースの読み書きが必要である. データベースには,データベース専用の独立したサーバーマシンが用いられることが一般的である. また,画像や動画などの容量の大きいデータは,また別のストレージサーバーに保存されることが多い. これらの API サーバー,データベースサーバー,ストレージサーバーはそれぞれ独立したサーバーマシンであり, AWS の言葉では EC2 による仮想インスタンスを想定してもらったらよい.

    多くのウェブサービスでは,多数のクライアントからのリクエストを処理するため,複数のサーバーマシンがクラウド内で起動し,負荷を分散するような設計がなされている. クライアントから来たリクエストを計算容量に余裕のあるサーバーに振り分けるような操作を Load balancing とよび,そのような操作を担当するマシンのことを Load balancer という.

    計算負荷を分散する目的で多数のインスタンスを起動するのはよいのだが,計算負荷が小さすぎてアイドリング状態にあるようではコストと電力の無駄遣いである. したがって,すべてのサーバーが常に目標とする計算負荷を維持するよう,計算の負荷に応じてクラスター内の仮想サーバーの数を動的に増減させるような仕組みが必要である. そのような仕組みをクラスターのスケーリングとよび,負荷の増大に応答して新しい仮想インスタンスをクラスターに追加する操作を scale-out,負荷の減少に応答してインスタンスをシャットダウンする操作を scale-in とよぶ. クラスターのスケーリングは, API サーバーではもちろんのこと,データベースサーバー・ストレージサーバーでも必要になる. ストレージサーバーでは,例えば頻繁にアクセスされるデータはキャッシュ領域に保存したり,データのコピーを複数作るなどのスケーリングが行われる. データベースサーバーも同様に,頻繁にアクセスされるデータのアクセスがパンクしてしまわないよう,分散的な処理が必要となる. このように,クラウドシステム内すべての箇所で,負荷が均一になるような調整が必要であり,開発者は多くの時間をそのチューニングに費やさなければならない. また,サービスの利用者の数などに応じてスケーリングの設定は常に見直される必要があり,継続的な開発が要求される.

    さらに問題を複雑にするのは,API サーバーで処理されるべきタスクが,非一様な点である. 非一様であるとは,たとえばタスク A は 3000 ミリ秒の実行時間と 512MB のメモリーを消費し,別のタスク B は 1000 ミリ秒の実行時間と 128MB のメモリーを消費する,というような状況を指している. 一つのサーバーマシンが計算負荷が異なる複数のタスクを処理する場合,クラスターのスケーリングはより複雑になる. この状況をシンプルにするために,1サーバーで実行するタスクは1種類に限る,という設計も可能であるが,そうするとで生まれる弊害も多い (ほとんど使われないタスクに対してもサーバー一台をまるまる割り当てなければならない = ほとんどアイドリング状態になってしまう,など).

    Serverful なクラウドシステム

    Serverless クラウドへ

    Serverful クラウド (従来型) で議論したように,クラスターのスケーリングはクラウドシステムの経済的効率とシステムの安定性を最大化するために必須の作業である. それを反映して,多くの開発者の時間が投資されてきた.

    クラスターのスケーリングはすべての開発者が何度も繰り返し行ってきた作業であり,いくつかの側面をテンプレート化し,共通化することができたならば開発のコストを大幅に削減できるだろう. それを実現するには,根本的なレベルからクラウドシステムの設計を考え直す必要がある. スケーリングを前提として考えることで,もっとシンプルで見通しがよいクラウドシステムの設計の仕組みはないだろうか? そのような動機が,サーバーレスアーキテクチャが誕生する背後にあった.

    従来の serverful なシステムでの最大の問題点は,サーバーをまるまる占有してしまうという点にある. すなわち, EC2 インスタンスを起動したとき,そのインスタンスは起動したユーザーだけが使えるものであり,計算のリソース (CPU や RAM) が独占的に割り当てられた状態になる. 固定した計算資源の割り当てがされてしまっているので,インスタンスの計算負荷が 0%であろうが 100%であろうが,均一の使用料金が起動時間に比例して発生する.

    サーバーレスアーキテクチャは,このような 独占的に割り当てられた計算リソースというものを完全に廃止することを出発点とする. サーバーレスアーキテクチャでは,計算のリソースは,クラウドプロバイダーがすべて管理する. クライアントは,仮想インスタンスを一台まるごと借りるのではなく,計算のタスクの需要が生まれる毎に,実行したいプログラム・コマンドをクラウドに提出する. クラウドプロバイダーは,自身のもつ巨大な計算リソースから空きを探し,提出されたプログラムを実行し,実行結果をクライアントに返す. 言い換えると,計算リソースのスケーリングやアロケーションなどはクラウドプロバイダーが一手に引き受け,ユーザーはジョブをサブミットすることに注力する,という枠組みである. これを図示すると, figure_title のようになる.

    従来のクラウドと Serverless クラウドの比較

    サーバーレスクラウドでは,スケーリングはすべてクラウドプロバイダーが引き受けるので,スケーラビリティーが保証されている. クライアントが同時に大量のタスクを送信した場合でも,クラウドプロバイダー側の独自の仕組みによってすべてのタスクが遅延なく実行される. また,サーバーレスクラウドを利用することで,クラウドのコストは実際に使用した計算の総量 (稼働時間) で決定されることになる. これは,計算の実行総量に関わらずインスタンスの起動時間で料金が決定されていた従来のシステムと比べて大きな違いである.

    サーバーレスクラウドは,従来のクラウドとは根本から異なったアプローチなので,コードの書き方やシステムの設計が大きく異なる. サーバーレスクラウドを開発・運用するには,サーバーレス固有の概念や用語に精通している必要がある. 以降では,実際にクラウドを動かしながら,サーバーレスをより具体的に体験していこう.

    従来型の(仮想インスタンスをたくさん起動するような)クラウドシステムは,賃貸と似ているかもしれない. 部屋を借りるというのは,その部屋でどれだけの時間を過ごそうが,月々の家賃は一定である. 同様に,仮想サーバーも,それがどれほどの計算を行っているかに関わらず,一定の料金が時間ごとに発生する.

    一方で,サーバーレスクラウドは,電気・水道・ガス料金 と似ている. こちらは,実際に使用した量に比例して料金が決定されている. サーバーレスクラウドも,実際に計算を行った総時間で料金が決まる仕組みになっている.

    サーバーレスクラウドを構成するコンポーネント

    サーバーレスアーキテクチャの概要がわかってきたところで,ここでは AWS においてサーバーレスクラウドを構成する様々なコンポーネントを紹介していこう. 特に, Lambda, S3, DynamoDB を取り上げ,解説する (figure_title). サーバーレスクラウドは,これらのコンポーネントを統合することで一つのシステムが出来上がる. ここでは, Lambda,S3,DynamoDB を利用する際に押さえておかなければならない知識を一通り説明しきる都合上,具体的なイメージがわきにくいかもしれない. が,続く (#sec_intro_serverless) でそれぞれについてハンズオン形式で演習を行うので,そこでさらに理解を深めれば大丈夫である.

    Lambda, S3, DynamoDB のアイコン

    Lambda

    AWS でサーバーレスコンピューティングの中心を担うのが, Lambda である. Lambda の使い方を figure_title に図示している. Lambda の仕組みはシンプルで,まずユーザーは実行したいプログラムのコードを事前に登録しておく. プログラムは, Python, Node.js, Ruby などの主要な言語がサポートされている. Lambda に登録されたひとつひとつのプログラムを関数 (Function) とよぶ. そして,関数を実行したいときに,invoke コマンドを Lambda に送信する. Lambda では, invoke のリクエストを受け取るとただちに (数ミリセカンドから数百ミリセカンド程度の時間で) プログラムの実行を開始する. そして,実行結果をクライアントやその他の計算機に返す.

    AWS Lambda

    このように,Lambda では占有された仮想インスタンスは存在せず,実行を待っているプログラムだけがある状態である. invoke のリクエストに応じて,プログラムが AWS の巨大な計算機プールのどこかに配置され,実行される. 同時に複数のリクエストが来た場合でも, AWS はそれらを実行するための計算リソースを割り当て,並列的に処理を行ってくれる. 原理上は,数千から数万のリクエストが同時に来たとしても, Lambda はそれらを同時に実行することができる. このような,占有された仮想サーバーの存在なしに,動的に関数を実行するサービスのことを総称して FaaS (Function as a Service) とよぶ.

    Lambda ではそれぞれの関数につき, 128MB から 10240MB のメモリーを使用することができる (執筆時点の仕様). また,実効的な CPU のパワーはメモリーの量に比例する形で割り当てられる. すなわち,タスクに割り当てたメモリーの量が多ければ多いほど,より多くの CPU リソースが割り当てられることになる (しかし, RAM と CPU パワーの具体的な換算表は AWS からは公開されていない). 実行時間は 100 ミリ秒の単位で記録され,実行時間に比例して料金が決定される. table_title は Lambda の利用料金表である (執筆時点で ap-north-east1 リージョンを選択した場合).

    Lambda の料金表
    Memory (MB)Price per 100ms

    128

    $0.0000002083

    512

    $0.0000008333

    1024

    $0.0000016667

    3008

    $0.0000048958

    実行時間に比例する料金に追加して,リクエストを送信するごとに発生する料金が設定されている. これは,百万回のリクエストにつき $0.2 である. たとえば, 128MB のメモリーを使用する関数を,それぞれ 200 ミリ秒,合計で 100 万回実行した場合, 0.0000002083 * 2 * 10^6 + 0.2 = $0.6 の料金となる. ウェブサーバーのデータベースの更新など簡単な計算であれば,200 ミリ秒程度で実行できる関数も多いことから,100 万回データベースの更新を行ったとしても,たった $0.6 しかコストが発生しないことになる. また,コードが実行されず待機状態になっている場合は,発生する料金は 0 である. このように,実際に意味のある処理が行われた時間にのみ,料金が発生する仕組みになっている.

    Lambda は比較的短時間で完了する,反復性の高いタスクの実行に向いている. データベースの読み書きはその典型的な例であるが,そのほかにも,画像のサイズをトリミングしたり,サーバーサイドで定期的に実行されるメンテナンス処理などの利用が考えられる. また,複数の Lambda をリレー式に繋げることも可能で,シンプルな処理を組み合わせることで複雑なロジックを表現することができる.

    上述の Lambda の料金計算は,説明のためコストに寄与する要素をいくつか省いている点は承知いただきたい. 例えば, DynamoDB の読み書きに関する料金や,ネットワークの通信にかかわるコストが考慮されていない.

    サーバーレスストレージ: S3

    サーバーレスの概念は,ストレージにも拡張されている.

    従来的なストレージ (ファイルシステム) では,必ずホストとなるマシンと OS が存在しなければならない. したがって,それほどパワーは必要ないまでも,ある程度の CPU リソースを割かなければならない. また,従来的なファイルシステムでは,データ領域のサイズは最初にディスクを初期化するときに決めなければならず,後から容量を増加させることはしばしば困難である (ZFS などのファイルシステムを使えばある程度は自由にファイルシステムのサイズを変更することは可能である). よって,従来的なクラウドでは,ストレージを借りる際にはあらかじめディスクのサイズを指定せねばならず,ディスクの中身が空であろうと満杯であろうと,同じ利用料金が発生することになる (figure_title).

    Simple Storage Service (S3) は,サーバーレスなストレージシステムを提供する (figure_title). S3 は従来的なストレージシステムと異なり, OS に"マウントする”という概念はない. 基本的に API を通じてデータの読み書きの操作が行われる. また,データの冗長化や暗号化,バックアップの作成など,通常ならば OS と CPU が介在しなければならない操作も, API を通じて行うことができる. S3 では事前に決められたディスク領域のサイズはなく,データを入れれば入れた分だけ,保存領域は拡大していく (仕様上はペタバイトスケールのデータを保存することが可能である). ストレージにかかる料金は,保存してあるデータの総容量で決定される.

    S3 と従来的なファイルシステムの比較

    S3 を利用する際に,料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 説明のため主要な事項のみ取り出している. 詳細は 公式ドキュメンテーション "Amazon S3 pricing" を参照).

    S3 の利用料金
    項目料金

    Data storage (First 50TB)

    $0.023 per GB per month

    PUT, COPY, POST, LIST requests (per 1,000 requests)

    $0.005

    GET, SELECT, and all other requests (per 1,000 requests)

    $0.0004

    Data Transfer IN To Amazon S3 From Internet

    $0

    Data Transfer OUT From Amazon S3 To Internet

    $0.09 per GB

    第一に,データの保存には $0.025 per GB のコストが月ごとに発生する. したがって,1000GB のデータを S3 に一ヵ月保存した場合, $25 の料金が発生することになる. また,PUT, COPY, POST などのリクエスト (=データを書き込む操作) に対しては,データ容量に関係なく,1000 回ごとに $0.005 のコストが発生する. GET, SELECT などのリクエスト (=データを読み込む操作) に対しては,1000 回ごとに $0.0004 のコストが発生する. また, S3 はデータを外に取り出す際の通信にもコストが生じる. 執筆時点では,S3 からインターネットを通じて外部にデータを転送 (data-out) すると $0.09 per GB のコストが発生する. データをインターネットを通じて S3 に入れる (data-in) 通信は無料で行える. また, AWS の 同じ Region 内のサービス (Lambda や EC2 など) にデータを転送するのは無料である. AWS のリージョンをまたいだデータの転送にはコストが発生する. いずれにせよ,サーバーレスの概念に則り,すべての料金が従量課金制で決定される設定になっている.

    サーバーレスデータベース: DynamoDB

    サーバーレスの概念は,データベースにも適用することができる.

    ここでいうデータベースとは, Web サービスなどにおけるユーザーや商品の情報を記録しておくための保存領域のことを指している. 従来的に有名なデータベースとしては MySQL, PostgreSQL, MongoDB などが挙げられる. データベースと普通のストレージの違いは,データの検索機能にある. 普通のストレージではデータは単純にディスクに書き込まれるだけだが, データベースでは検索がより効率的になるようなデータの配置がされたり, 頻繁にアクセスされるデータはメモリーにキャッシュされるなどの機能が備わっている. これにより,巨大なデータの中から,興味のある要素を高速に取得することができる.

    このような検索機能を実現するには,当然 CPU の存在が必須である. したがって,従来的なデータベースを構築する際は,ストレージ領域に加えて,たくさんの CPU コアを搭載したマシンが用いられることが多い. また,データベースが巨大な場合は複数マシンにまたがった分散型のシステムが設計される. 分散型システムの場合は, Serverful クラウド (従来型) で議論したようにデータベースへのアクセス負荷に応じて適切なスケーリングがなされる必要がある.

    DynamoDB は, AWS が提供しているサーバーレスな分散型データベースである. サーバーレスであるので,占有されたデータベース用仮想インスタンスは存在せず, API を通じてデータの書き込み・読み出し・検索などの操作を行う. S3 と同様に,データ保存領域の上限は定められておらず,データを入れれば入れた分だけ,保存領域は拡大していく. また,データベースへの負荷が増減したときのスケーリングは, DynamoDB が自動で行うので,ユーザーは心配する必要はない.

    DynamoDB での利用料金の計算はやや複雑なのだが, "On-demand Capacity" というモードで使用した場合の料金に関わってくる主要な事項をまとめたのが table_title である (us-east-1 リージョンのもの. 詳細は 公式ドキュメンテーション "Pricing for On-Demand Capacity" を参照).

    DynamoDB の利用料金
    項目料金

    Write request units

    $1.25 per million write request units

    Read request units

    $0.25 per million read request units

    Data storage

    $0.25 per GB-month

    DynamoDB ではデータの書き込み操作の単位を write request unit とよび,データの読み込み操作の単位を read request unit とよぶ. 基本的に, 1kB 以下のデータを一度書き込むと 1 write request unit を消費し,4kB 以下のデータを一度読み込むと 1 read request unit を消費する (詳しくは 公式ドキュメンテーション "Read/Write Capacity Mode" を参照のこと). write request units は 100 万回ごとに $1.25, read request units は 100 万回ごとに $0.25 のコストが設定されている. また,保存されたデータ容量に対して $0.25 per GB のコストが月ごとに発生する. DynamoDB は高速な検索機能などを備えたデータベースであるので, GB あたりのストレージコストは S3 に比べ 10 倍程度高い. DynamoDB のデータの転送に関わるコストは,同じリージョン内ならば data-in,data-out ともに $0 である. リージョンをまたいだ通信には別途コストが発生する.

    その他のサーバーレスクラウドの構成要素

    以上で紹介した Lambda, S3, DynamoDB がサーバーレスクラウドの中で最も使用する頻度が高いサービスになる. その他のサーバーレスクラウドの構成要素を以下に列挙する. いくつかについては,今後のハンズオンを行う中で改めて解説を行う.

    • API Gateway: API を構築する際のルーティングを担う. (#sec_bashoutter) で取り上げる.

    • Fargate: (#sec_fargate_qabot) で触れた Fargate も,サーバーレスクラウドの要素の一部である. Lambda との違いは,Lambda よりも大容量のメモリーや CPU を要するような計算などを行うことができる点が挙げられる.

    • Simple Notification Service (SNS): サーバーレスのサービス間でイベントをやり取りするためのサービス.

    • Step Functions: サーバーレスのサービス間のオーケストレーションを担う.

    サーバーレスアーキテクチャは万能か?

    この問いへの答えは,筆者は NO であると考える.

    ここまで,サーバーレスの利点を強調して説明をしてきたが,まだまだ新しい技術なだけに,欠点,あるいはサーバーフルなシステムに劣る点は数多くある.

    大きな欠点を一つあげるとすれば,サーバーレスのシステムは各クラウドプラットフォームに固有なものなので,特定のプラットフォームでしか運用できないシステムになってしまう点であろう. AWS で作成したサーバーレスのシステムを, Google のクラウドに移植するには,かなり大掛かりなプログラムの書き換えが必要になる. 一方, serverful なシステムであれば,プラットフォーム間のマイグレーションは比較的簡単に行うことができる. クラウドプロバイダーとしては,自社のシステムへの依存度を強めることで,顧客を離さないようにするという狙いがあるのだろう…

    その他,サーバーレスコンピューティングの欠点や今後の課題などは,次の論文で詳しく議論されている. 興味のある読者はぜひ読んでいただきたい.

    + \ No newline at end of file diff --git a/development/aws/webserver.html b/development/aws/webserver.html index b22bb4f8..a6322ab0 100644 --- a/development/aws/webserver.html +++ b/development/aws/webserver.html @@ -5,16 +5,16 @@ Web サービスの作り方 | Toshiki's Note - + - + - + - + @@ -37,8 +37,8 @@ -
    Skip to content

    Web サービスの作り方

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:1.4k
    Reading:5 min

    ここからが,本書第三部の内容になる. これまでのセクションでは,仮想サーバーをクラウド上に起動し,そこで計算を走らせる方法について解説をしてきた. EC2, ECS, Fargate, Batch などを利用して,動的にスケールするクラスターを構成し,並列にタスクを実行するクラウドシステムを実装してきた. 振り返ると,これまで紹介してきた内容は,自分自身が行いたい計算をクラウドを駆使することで実現する,という用途にフォーカスしていたことに気がつくだろう. 一方で,広く一般の人々に使ってもらえるような計算サービス・データベースを提供する,というのもクラウドの重要な役割として挙げられる.

    本章から始まる第三部では,前回までとは少し方向性を変え,どのようにしてクラウド上にアプリケーションを展開し,広く一般の人に使ってもらうか,という点を講義したいと思う. これを通じて,どのようにして世の中のウェブサービスができ上がっているのかを知り,さらにどうやって自分でそのようなアプリケーションをゼロから構築するのか,という点を学んでもらう. その過程で,サーバーレスアーキテクチャという最新のクラウド設計手法を解説する.

    その前準備として,本章ではどのようにしてウェブサービスが出来上がっているのか,その背後にある技術の概要を解説する. 用語の解説が中心となるが,後のハンズオンを実装するために必須の知識であるので,理解して前に進むよう心がけよう.

    ウェブサービスの仕組み  — Twitter を例に

    あなたがパソコンやスマートフォンから Twitter, Facebook, YouTube などのウェブサービスにアクセスしたとき,実際にどのようなことが行われ,コンテンツが提示されているのだろうか?

    HTTP を通じたサーバーとクライアントのデータのやり取りは,すでに知っている読者も多いだろうし,逆にすべて解説しようとすると紙面が足りないので,ここではエッセンスの説明のみにとどめる. 以降では Twitter を具体例として,背後にあるサーバーとクライアントの間の通信を概説しよう. 概念図としては figure_title のような通信がクライアントとサーバーの間で行われていることになる.

    クライアントと Web サーバーの通信の概念図

    前提として,クライアントとサーバーの通信は HTTP (Hypertext Transfer Protocol) を使って行われる. また,最近では,暗号化された HTTP である HTTPS (HTTPS (Hypertext Transfer Protocol Secure)) を用いることがスタンダードになってきている. 第一のステップとして,クライアントは HTTP(S) 通信によってサーバーから静的なコンテンツを取得する. 静的なコンテンツとは, HTML (Hyptertext Markup Language) で記述されたウェブページの文書本体, CSS (Cascading Style Sheets) で記述されたページのデザインやレイアウトファイル,そして JavaScript (JS) で記述されたページの動的な挙動を定義したプログラム,が含まれる. Twitter を含む現代的なウェブアプリケーションの設計では,この静的なファイル群はページの”枠”を定義するだけで,中身となるコンテンツ (例: ツイートの一覧) は別途 API (Application Programming Interface) によって取得されなければならない. そこで,クライアントは先のステップで取得された JavaScript で定義されたプログラムに従って,サーバーに API を送信し,ツイートや画像データを取得する. この際,テキストデータのやり取りには JSON (JavaScript Object Notation) というフォーマットが用いられることが多い. 画像や動画などのコンテンツも同様に API により取得される. このようにして取得されたテキストや画像が,HTML の文書に埋め込まれることで,最終的にユーザーに提示されるページが完成するのである. また,新しいツイートを投稿するときにも,クライアントから API を通じてサーバーのデータベースにデータが書き込まれる.

    REST API

    API (Application Programming Interface) とはこれまで何度も出てきた言葉であるが,ここではよりフォーマルな定義付けを行う. API とはあるソフトウェア・アプリケーションが,外部のソフトウェアに対してコマンドやデータをやり取りするための媒介の一般的総称である. とくに,ウェブサービスの文脈では,サーバーが外界に対して提示しているコマンドの一覧のことを意味する. クライアントは,提示されている API から適切なコマンドを使うことによって,所望のデータを取得したり,あるいはサーバーにデータを送信したりする.

    とくに,ウェブの文脈では REST (Representational State Transfer) とよばれる設計思想に基づいた API が現在では最も一般的に使われている. REST の設計指針に従った API のことを REST API あるいは RESTful API とよんだりする.

    REST API は, figure_title に示したような MethodURI (Universal Resource Identifier) の組からなる.

    REST API

    Method (メソッド) とは,どのような操作を行いたいかを抽象的に表す,"動詞" として捉えることができる. メソッドには HTTP 規格で定義された 9 個の動詞 (verb) を使用することができる. この中でも, GET, POST, PUT, PATCH, DELETE の 5 個が最も頻繁に使用される (table_title). この 5 つのメソッドによる操作を総称して CRUD (create, read, update, and delete) とよぶ.

    REST API Methods
    メソッド意図される動作

    GET

    要素を取得する

    POST

    新しい要素を作成する

    PUT

    既存の要素を新しい要素と置き換える

    PATCH

    既存の要素の一部を更新する

    DELETE

    要素を削除する

    一方, URI は操作が行われる対象,すなわち "目的語" を表す. ウェブの文脈では操作が行われる対象のことをしばしば リソース とよぶ. URI は多くの場合 http または https から始まるウェブサーバーのアドレスから始まり, / (スラッシュ) 以降に所望のリソースのパスが指定される. figure_title の例で言えば, https://api.twitter.com というアドレスの /1.1/status/home_timeline というリソースを取得 (GET) せよ,という意味になる (なお,ここで 1.1 という数字は API のバージョンを示している). この API リクエストによって,ユーザーのホームのタイムラインのツイートの一覧が取得される.

    REST API のメソッドには, table_title で挙げたもの以外に, HTTP プロトコルで定義されているほかのメソッド (OPTIONS, TRACE など) を用いることもできるが,あまり一般的ではない.

    また,これらのメソッドだけでは動詞として表現しきれないこともあるが, URI の名前でより意味を明確にすることもある. メソッドの使い方も,要素を削除する際は必ず DELETE を使わなければならない,という決まりもなく,たとえば, Twitter API でツイートを消す API は POST statuses/destroy/:id で定義されている. 最終的には,各ウェブサービスが公開している API ドキュメンテーションを読んで,それぞれの API がどんな操作をするのかを調べる必要がある.

    REST の概念は 2000 年代初頭に確立され,今日の API 設計のスタンダードとなった. 一方で,ウェブのテクノロジーが進歩するにつれて,新たな API の設計アプローチの需要も高まっている. 近年とくに人気を集めているのが, GraphQL と呼ばれる API の設計方法である. GraphQL は Facebook 社によって最初に作られ,現在は GraghQL Foundation によって維持と更新がされている. GraphQL を使用すると,クライアントは REST と比較してより柔軟性の高いデータのクエリを行うことができるなど,いくつかの利点がある. キーワードだけでも知っておくと,今後役に立つだろう.

    Twitter API

    もう少し具体的にウェブサービスの API を体験する目的で,ここでは Twitter の API を見てみよう. Twitter が提供している API の一覧は Twitter の Developer Documentation で見ることができる. いくつかの代表的な API を table_title にまとめた.

    Twitter API
    エンドポイント動作

    GET statuses/home_timeline

    ホームのタイムラインのツイートの一覧を取得する.

    GET statuses/show/:id

    :id で指定されたツイートの詳細情報を取得する.

    GET search

    ツイートの検索を実行する.

    POST statuses/update

    新しいツイートを投稿する.

    POST media/upload

    画像をアップロードする

    POST statuses/destroy/:id

    :id で指定されたツイートを削除する.

    POST statuses/retweet/:id

    :id で指定されたツイートをリツイートする.

    POST statuses/unretweet/:id

    :id で指定されたツイートのリツイートを取り消す.

    POST favorites/create

    選択したツイートを"いいね"する.

    POST favorites/destroy

    選択したツイートを"いいね"を取り消す.

    この API リストをもとに, Twitter のアプリまたはウェブサイトを開いたときに起こるクライアントとサーバーの通信をシミュレートしてみよう.

    ユーザーが Twitter を開くと,まず最初に GET statuses/home_timeline の API リクエストによって,ユーザーのホームのタイムラインのツイートのリストが取得される. 個々のツイートは JSON 形式のデータになっており, id, text, user, coordinates, entities などの属性を含む. id はツイートに固有な ID を表し, text はツイートの本文を含んでいる. user はツイートを投稿したユーザーの名前やプロフィール画像の URL などを含んだ JSON データになっている. coordinates にはツイートが発信された地理的な座標が記録されている. また, entities にはツイートに関連するメディアファイル (画像など) のリンクなどの情報が埋め込まれている. GET statuses/home_timeline からは直近のツイートのリスト (リストが長すぎる場合は途中で切られたもの) が取得される. もしツイートの ID を知っている場合は GET statuses/show/:id を呼ぶことによって, :id パラメータで指定された特定のツイートを取得することができる.

    ツイートの検索を行うためには GET search API を使用する. この API には,ツイートに含まれる単語や,ハッシュタグ,ツイートの発信された日時や場所など,様々なクエリの条件を渡すことができる. API からは, GET statuses/home_timeline などと同様, JSON 形式のツイートのデータが返される.

    ユーザーが新しいツイートを投稿するには POST statuses/update のエンドポイントを利用する. POST statuses/update には,ツイートの文章や,リプライの場合はリプライ先のツイートの ID などのデータを送信する. また,ツイートに画像データを添付したい場合は, POST media/upload を併せて使用する. ツイートの削除を行うには, POST statuses/destroy/:id を用いる.

    そのほか,頻繁に行われる操作としては, POST statuses/retweet/:idPOST statuses/unretweet/:id がある. これらは, :id で指定されるツイートに対して,それぞれリツイートを実行あるいは取り消すための API である. また, POST favorites/createPOST favorites/destroy を使用することによって,選択されたツイートに"いいね"を追加したり,取り消したりする操作を行う.

    このような一連の操作が, Twitter のアプリの背後では行われている. また,自分自身でボットを作成したい場合は,これらの API を適切に組み合わせ,カスタムのプログラムを書くことで実現される.

    このように, API はあらゆるウェブサービスを作るうえで一番基礎となる要素である. 次からの章では本章で紹介した用語が何度も出てくるので,頭の片隅に置いたうえで読み進めていただきたい.

    - +
    Skip to content

    Web サービスの作り方

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:1.4k
    Reading:5 min

    ここからが,本書第三部の内容になる. これまでのセクションでは,仮想サーバーをクラウド上に起動し,そこで計算を走らせる方法について解説をしてきた. EC2, ECS, Fargate, Batch などを利用して,動的にスケールするクラスターを構成し,並列にタスクを実行するクラウドシステムを実装してきた. 振り返ると,これまで紹介してきた内容は,自分自身が行いたい計算をクラウドを駆使することで実現する,という用途にフォーカスしていたことに気がつくだろう. 一方で,広く一般の人々に使ってもらえるような計算サービス・データベースを提供する,というのもクラウドの重要な役割として挙げられる.

    本章から始まる第三部では,前回までとは少し方向性を変え,どのようにしてクラウド上にアプリケーションを展開し,広く一般の人に使ってもらうか,という点を講義したいと思う. これを通じて,どのようにして世の中のウェブサービスができ上がっているのかを知り,さらにどうやって自分でそのようなアプリケーションをゼロから構築するのか,という点を学んでもらう. その過程で,サーバーレスアーキテクチャという最新のクラウド設計手法を解説する.

    その前準備として,本章ではどのようにしてウェブサービスが出来上がっているのか,その背後にある技術の概要を解説する. 用語の解説が中心となるが,後のハンズオンを実装するために必須の知識であるので,理解して前に進むよう心がけよう.

    ウェブサービスの仕組み  — Twitter を例に

    あなたがパソコンやスマートフォンから Twitter, Facebook, YouTube などのウェブサービスにアクセスしたとき,実際にどのようなことが行われ,コンテンツが提示されているのだろうか?

    HTTP を通じたサーバーとクライアントのデータのやり取りは,すでに知っている読者も多いだろうし,逆にすべて解説しようとすると紙面が足りないので,ここではエッセンスの説明のみにとどめる. 以降では Twitter を具体例として,背後にあるサーバーとクライアントの間の通信を概説しよう. 概念図としては figure_title のような通信がクライアントとサーバーの間で行われていることになる.

    クライアントと Web サーバーの通信の概念図

    前提として,クライアントとサーバーの通信は HTTP (Hypertext Transfer Protocol) を使って行われる. また,最近では,暗号化された HTTP である HTTPS (HTTPS (Hypertext Transfer Protocol Secure)) を用いることがスタンダードになってきている. 第一のステップとして,クライアントは HTTP(S) 通信によってサーバーから静的なコンテンツを取得する. 静的なコンテンツとは, HTML (Hyptertext Markup Language) で記述されたウェブページの文書本体, CSS (Cascading Style Sheets) で記述されたページのデザインやレイアウトファイル,そして JavaScript (JS) で記述されたページの動的な挙動を定義したプログラム,が含まれる. Twitter を含む現代的なウェブアプリケーションの設計では,この静的なファイル群はページの”枠”を定義するだけで,中身となるコンテンツ (例: ツイートの一覧) は別途 API (Application Programming Interface) によって取得されなければならない. そこで,クライアントは先のステップで取得された JavaScript で定義されたプログラムに従って,サーバーに API を送信し,ツイートや画像データを取得する. この際,テキストデータのやり取りには JSON (JavaScript Object Notation) というフォーマットが用いられることが多い. 画像や動画などのコンテンツも同様に API により取得される. このようにして取得されたテキストや画像が,HTML の文書に埋め込まれることで,最終的にユーザーに提示されるページが完成するのである. また,新しいツイートを投稿するときにも,クライアントから API を通じてサーバーのデータベースにデータが書き込まれる.

    REST API

    API (Application Programming Interface) とはこれまで何度も出てきた言葉であるが,ここではよりフォーマルな定義付けを行う. API とはあるソフトウェア・アプリケーションが,外部のソフトウェアに対してコマンドやデータをやり取りするための媒介の一般的総称である. とくに,ウェブサービスの文脈では,サーバーが外界に対して提示しているコマンドの一覧のことを意味する. クライアントは,提示されている API から適切なコマンドを使うことによって,所望のデータを取得したり,あるいはサーバーにデータを送信したりする.

    とくに,ウェブの文脈では REST (Representational State Transfer) とよばれる設計思想に基づいた API が現在では最も一般的に使われている. REST の設計指針に従った API のことを REST API あるいは RESTful API とよんだりする.

    REST API は, figure_title に示したような MethodURI (Universal Resource Identifier) の組からなる.

    REST API

    Method (メソッド) とは,どのような操作を行いたいかを抽象的に表す,"動詞" として捉えることができる. メソッドには HTTP 規格で定義された 9 個の動詞 (verb) を使用することができる. この中でも, GET, POST, PUT, PATCH, DELETE の 5 個が最も頻繁に使用される (table_title). この 5 つのメソッドによる操作を総称して CRUD (create, read, update, and delete) とよぶ.

    REST API Methods
    メソッド意図される動作

    GET

    要素を取得する

    POST

    新しい要素を作成する

    PUT

    既存の要素を新しい要素と置き換える

    PATCH

    既存の要素の一部を更新する

    DELETE

    要素を削除する

    一方, URI は操作が行われる対象,すなわち "目的語" を表す. ウェブの文脈では操作が行われる対象のことをしばしば リソース とよぶ. URI は多くの場合 http または https から始まるウェブサーバーのアドレスから始まり, / (スラッシュ) 以降に所望のリソースのパスが指定される. figure_title の例で言えば, https://api.twitter.com というアドレスの /1.1/status/home_timeline というリソースを取得 (GET) せよ,という意味になる (なお,ここで 1.1 という数字は API のバージョンを示している). この API リクエストによって,ユーザーのホームのタイムラインのツイートの一覧が取得される.

    REST API のメソッドには, table_title で挙げたもの以外に, HTTP プロトコルで定義されているほかのメソッド (OPTIONS, TRACE など) を用いることもできるが,あまり一般的ではない.

    また,これらのメソッドだけでは動詞として表現しきれないこともあるが, URI の名前でより意味を明確にすることもある. メソッドの使い方も,要素を削除する際は必ず DELETE を使わなければならない,という決まりもなく,たとえば, Twitter API でツイートを消す API は POST statuses/destroy/:id で定義されている. 最終的には,各ウェブサービスが公開している API ドキュメンテーションを読んで,それぞれの API がどんな操作をするのかを調べる必要がある.

    REST の概念は 2000 年代初頭に確立され,今日の API 設計のスタンダードとなった. 一方で,ウェブのテクノロジーが進歩するにつれて,新たな API の設計アプローチの需要も高まっている. 近年とくに人気を集めているのが, GraphQL と呼ばれる API の設計方法である. GraphQL は Facebook 社によって最初に作られ,現在は GraghQL Foundation によって維持と更新がされている. GraphQL を使用すると,クライアントは REST と比較してより柔軟性の高いデータのクエリを行うことができるなど,いくつかの利点がある. キーワードだけでも知っておくと,今後役に立つだろう.

    Twitter API

    もう少し具体的にウェブサービスの API を体験する目的で,ここでは Twitter の API を見てみよう. Twitter が提供している API の一覧は Twitter の Developer Documentation で見ることができる. いくつかの代表的な API を table_title にまとめた.

    Twitter API
    エンドポイント動作

    GET statuses/home_timeline

    ホームのタイムラインのツイートの一覧を取得する.

    GET statuses/show/:id

    :id で指定されたツイートの詳細情報を取得する.

    GET search

    ツイートの検索を実行する.

    POST statuses/update

    新しいツイートを投稿する.

    POST media/upload

    画像をアップロードする

    POST statuses/destroy/:id

    :id で指定されたツイートを削除する.

    POST statuses/retweet/:id

    :id で指定されたツイートをリツイートする.

    POST statuses/unretweet/:id

    :id で指定されたツイートのリツイートを取り消す.

    POST favorites/create

    選択したツイートを"いいね"する.

    POST favorites/destroy

    選択したツイートを"いいね"を取り消す.

    この API リストをもとに, Twitter のアプリまたはウェブサイトを開いたときに起こるクライアントとサーバーの通信をシミュレートしてみよう.

    ユーザーが Twitter を開くと,まず最初に GET statuses/home_timeline の API リクエストによって,ユーザーのホームのタイムラインのツイートのリストが取得される. 個々のツイートは JSON 形式のデータになっており, id, text, user, coordinates, entities などの属性を含む. id はツイートに固有な ID を表し, text はツイートの本文を含んでいる. user はツイートを投稿したユーザーの名前やプロフィール画像の URL などを含んだ JSON データになっている. coordinates にはツイートが発信された地理的な座標が記録されている. また, entities にはツイートに関連するメディアファイル (画像など) のリンクなどの情報が埋め込まれている. GET statuses/home_timeline からは直近のツイートのリスト (リストが長すぎる場合は途中で切られたもの) が取得される. もしツイートの ID を知っている場合は GET statuses/show/:id を呼ぶことによって, :id パラメータで指定された特定のツイートを取得することができる.

    ツイートの検索を行うためには GET search API を使用する. この API には,ツイートに含まれる単語や,ハッシュタグ,ツイートの発信された日時や場所など,様々なクエリの条件を渡すことができる. API からは, GET statuses/home_timeline などと同様, JSON 形式のツイートのデータが返される.

    ユーザーが新しいツイートを投稿するには POST statuses/update のエンドポイントを利用する. POST statuses/update には,ツイートの文章や,リプライの場合はリプライ先のツイートの ID などのデータを送信する. また,ツイートに画像データを添付したい場合は, POST media/upload を併せて使用する. ツイートの削除を行うには, POST statuses/destroy/:id を用いる.

    そのほか,頻繁に行われる操作としては, POST statuses/retweet/:idPOST statuses/unretweet/:id がある. これらは, :id で指定されるツイートに対して,それぞれリツイートを実行あるいは取り消すための API である. また, POST favorites/createPOST favorites/destroy を使用することによって,選択されたツイートに"いいね"を追加したり,取り消したりする操作を行う.

    このような一連の操作が, Twitter のアプリの背後では行われている. また,自分自身でボットを作成したい場合は,これらの API を適切に組み合わせ,カスタムのプログラムを書くことで実現される.

    このように, API はあらゆるウェブサービスを作るうえで一番基礎となる要素である. 次からの章では本章で紹介した用語が何度も出てくるので,頭の片隅に置いたうえで読み進めていただきたい.

    + \ No newline at end of file diff --git a/development/file-naming-convention.html b/development/file-naming-convention.html index f409255b..37dbe53f 100644 --- a/development/file-naming-convention.html +++ b/development/file-naming-convention.html @@ -5,15 +5,15 @@ File Name Conventions | Toshiki's Note - + - + - + - + @@ -36,74 +36,74 @@ -
    Skip to content

    File Name Conventions

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:1.2k
    Reading:7 min

    A collection of guidelines for writing file names used in web projects.

    Possible characters

    Use dashes as delimiters

    • You should use dashes (-) as delimiters.
    • Periods are allowed in some cases, such as for languages and conditions.
    • Never use spaces or underscores. Spaces are converted to %20 in URLs or can break an URL when shared. Underscores are difficult to see when the file name is displayed as an underlined link. Although the use of underscores does not impact your ranking that much, Google advices not to use underscores.
    • Exceptions apply for functional requirements, such as for Sass partials. A leading underscore informs the Sass compiler a file is only a partial file and should never be generated into a stand alone CSS file.

    Right:

    file-name-with-dashes.en.min.html
    file-name-with-dashes.en.min.html

    Do not use special characters

    Avoid using non-alphanumeric characters in file names, such as: '*' ':' '\' '/' '<' '>' '|' '"' '!' '?' '[' ']' ';' '=' '+' '&' '£' '$' '' '%' or ','. These characters can have special meaning in programming languages or can cause problems with different operating systems.

    Use lowercase, never uppercase

    We should always consider URLs as case-sensitive according to W3.org. Therefore, use lowercase to reduces errors when typing URLs.

    Write sections of a file name in a consistent order

    Sections should be written in this order:

    1. Description
    2. Number
    3. Date
    4. Target device, image size, pixel density
    5. Version number
    6. Status
    7. Language code
    8. File conditions

    Possible combinations

    description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
    -description.min.js
    -description.en.html
    -description-01.jpg
    -description-02.jpg
    -description-1024x768_2x.jpg
    -description-desk_2x.jpg
    description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
    -description.min.js
    -description.en.html
    -description-01.jpg
    -description-02.jpg
    -description-1024x768_2x.jpg
    -description-desk_2x.jpg

    Write description for developers and users

    Don't be afraid to write long informative file names. Few people type a file name manually and most operating systems support 255 characters. But only add information that makes it easy for users and developers to recognize files from one another at a glance. For the description use information such as:

    • type of data
    • project name or acronym
    • subjects
    • people's names
    • characteristics
    • location

    Give your images detailed, informative filenames The filename can give Google clues about the subject matter of the image. Try to make your filename a good description of the subject matter of the image. For example, my-new-black-kitten.jpg is a lot more informative than IMG00023.JPG. Descriptive filenames can also be useful to users: If we're unable to find suitable text in the page on which we found the image, we'll use the filename as the image's snippet in our search results. - Google, 2015, Image publishing guidelines

    Keep people's names compact

    Sometimes you want to include the name of a person in the file name, e.g. the author or the person in the photo.

    • Write names without word delimiters.
    • Only write initials for the first name and write the last name in full. There are two exceptions: (1) when the last name or final file name is very long you may use initials for the last name; (2) when there is already a person with the same combination, you may write the first name in full.
    • If people have exactly the same name written in full, you can add a number: firstnamelastname2.

    Right:

    bvandebiezen.jpg
    -shoogenhout.jpg
    -a-very-long-description-with-name-bvdb.jpg
    -asmith.jpg
    -adamsmith.jpg
    -adamsmith2.jpg
    bvandebiezen.jpg
    -shoogenhout.jpg
    -a-very-long-description-with-name-bvdb.jpg
    -asmith.jpg
    -adamsmith.jpg
    -adamsmith2.jpg

    Use two or more digits to distinguish sequential files with the same description

    • Start number with a dash as a delimiter.
    • Add a zero to single digit numbers, e.g. '01' instead of '1'.
    • Numbers may also be placed before the description if needed. A dash will still be used as delimiter with the description.

    Right:

    description-01.jpg
    -description-02.jpg
    -description-03.jpg
    -description-04.jpg
    -
    -01-description.jpg
    -02-description.jpg
    -03-description.jpg
    -04-description.jpg
    description-01.jpg
    -description-02.jpg
    -description-03.jpg
    -description-04.jpg
    -
    -01-description.jpg
    -02-description.jpg
    -03-description.jpg
    -04-description.jpg

    Keep dates or date ranges compact and start with year

    • Write dates without delimiters.
    • Always use four digits for years, two digits for months and two digits for days.
    • Start with year, then month, and end with day if available: yyyymmdd, yyyymm, or yyyy. This makes sure similar file names are sorted by date when sorted alphabetically.
    • Use a double dash to separate two dates describing an interval: yyyy--yyyy. Start with the earliest date.

    Right:

    description-20150401.php
    -description-201504.php
    -description-2015.php
    -description-2000--2010.php
    description-20150401.php
    -description-201504.php
    -description-2015.php
    -description-2000--2010.php

    See 'ISO 8601' for further reading.

    Use special modifiers for target devices, image sizes or media queries, and pixel densities.

    Modifiers are inspired by Apple iOS naming conventions. There are some differences. Apple uses '@'as a delimiter for the section indicating higher resolution images, for example '@2x' for retina images. Because '@' is a reserved character and can create problems, we use Bourbon's convention: an underscore. Also, Apple uses a tilde (~) as a delimiter for a section indicating specific devices. Because also a tilde can create problems, we suggest to simply use a dash.

    • Order should be: (1) target device or media query, (2) size, (3) pixel density.
    • Start target device or media queries with a dash (-) as delimiter.
    • Start image sizes with a dash (-) as delimiter.
    • Start pixel density with an underscore (_) as delimiter, for example '_2x' or '_3x'.
    • When only a width or height is available or applicable, add a 'w' for width or 'h' for height directly after the the amount of pixels.
    • When both measurements are available, do not add a 'w' or 'h' and separate the width and height with an 'x'.
    • When both the width and height should not exceed a dimension but the images should keep the original aspect ratio, add a 'max' (maximum) after the amount of pixels.

    Right:

    description_2x.jpg
    -description-lap.jpg
    -description-desk.jpg
    -description-lap_2x.jpg
    -description-palm-1024w_2x.jpg
    -description-iphone5-568h_2x.jpg
    -description-palm-1024x768_2x.jpg
    -description-40max.jpg
    description_2x.jpg
    -description-lap.jpg
    -description-desk.jpg
    -description-lap_2x.jpg
    -description-palm-1024w_2x.jpg
    -description-iphone5-568h_2x.jpg
    -description-palm-1024x768_2x.jpg
    -description-40max.jpg

    Use version numbers if available

    • Start version with a dash (-) as delimiter.
    • Use periods (.) to separate point releases.
    • Always add trailing zeros to major releases, e.g. '2.0' instead of '2'.
    • Types, such as 'a' (alpha), 'b' (beta), 'rc1' (release candidate 1) can be added without delimiters.

    Right:

    description-0.5.js
    -description-1.0b.js
    -description-1.0rc1.js
    description-0.5.js
    -description-1.0b.js
    -description-1.0rc1.js

    Add status when needed

    • You can optionally add a file status such as 'draft' and 'published'.
    • Start status with a dash.

    Right:

    description-draft.md
    description-draft.md

    Add language code only when different languages are available

    • Use a period to separate the language code from the rest of the file name.
    • Use ISO 639-1, two-letter codes, for languages.
    • Only add languages when different languages are available.

    Right:

    description.nl.txt
    -description.en.txt
    description.nl.txt
    -description.en.txt

    Add file conditions just before the file extension

    • The file condition should be the last part, just before the file extension.
    • Use a period (.) to separate the condition from the rest of the file name.
    • Use periods (.) as a delimiter for different conditions.

    Right:

    description.min.js
    -description.custom1234.min.js
    description.min.js
    -description.custom1234.min.js

    Rewrite original file names not following conventions

    It is not preferred to keep file names in it's original format if it doesn't match your file name conventions. But in some cases it is easier to keep the file name untouched. Sometimes you want to easily replace a file with a newer one from the original source in the future.

    - +
    Skip to content

    File Name Conventions

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:1.2k
    Reading:7 min

    A collection of guidelines for writing file names used in web projects.

    Possible characters

    Use dashes as delimiters

    • You should use dashes (-) as delimiters.
    • Periods are allowed in some cases, such as for languages and conditions.
    • Never use spaces or underscores. Spaces are converted to %20 in URLs or can break an URL when shared. Underscores are difficult to see when the file name is displayed as an underlined link. Although the use of underscores does not impact your ranking that much, Google advices not to use underscores.
    • Exceptions apply for functional requirements, such as for Sass partials. A leading underscore informs the Sass compiler a file is only a partial file and should never be generated into a stand alone CSS file.

    Right:

    file-name-with-dashes.en.min.html
    file-name-with-dashes.en.min.html

    Do not use special characters

    Avoid using non-alphanumeric characters in file names, such as: '*' ':' '\' '/' '<' '>' '|' '"' '!' '?' '[' ']' ';' '=' '+' '&' '£' '$' '' '%' or ','. These characters can have special meaning in programming languages or can cause problems with different operating systems.

    Use lowercase, never uppercase

    We should always consider URLs as case-sensitive according to W3.org. Therefore, use lowercase to reduces errors when typing URLs.

    Write sections of a file name in a consistent order

    Sections should be written in this order:

    1. Description
    2. Number
    3. Date
    4. Target device, image size, pixel density
    5. Version number
    6. Status
    7. Language code
    8. File conditions

    Possible combinations

    description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
    +description.min.js
    +description.en.html
    +description-01.jpg
    +description-02.jpg
    +description-1024x768_2x.jpg
    +description-desk_2x.jpg
    description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
    +description.min.js
    +description.en.html
    +description-01.jpg
    +description-02.jpg
    +description-1024x768_2x.jpg
    +description-desk_2x.jpg

    Write description for developers and users

    Don't be afraid to write long informative file names. Few people type a file name manually and most operating systems support 255 characters. But only add information that makes it easy for users and developers to recognize files from one another at a glance. For the description use information such as:

    • type of data
    • project name or acronym
    • subjects
    • people's names
    • characteristics
    • location

    Give your images detailed, informative filenames The filename can give Google clues about the subject matter of the image. Try to make your filename a good description of the subject matter of the image. For example, my-new-black-kitten.jpg is a lot more informative than IMG00023.JPG. Descriptive filenames can also be useful to users: If we're unable to find suitable text in the page on which we found the image, we'll use the filename as the image's snippet in our search results. - Google, 2015, Image publishing guidelines

    Keep people's names compact

    Sometimes you want to include the name of a person in the file name, e.g. the author or the person in the photo.

    • Write names without word delimiters.
    • Only write initials for the first name and write the last name in full. There are two exceptions: (1) when the last name or final file name is very long you may use initials for the last name; (2) when there is already a person with the same combination, you may write the first name in full.
    • If people have exactly the same name written in full, you can add a number: firstnamelastname2.

    Right:

    bvandebiezen.jpg
    +shoogenhout.jpg
    +a-very-long-description-with-name-bvdb.jpg
    +asmith.jpg
    +adamsmith.jpg
    +adamsmith2.jpg
    bvandebiezen.jpg
    +shoogenhout.jpg
    +a-very-long-description-with-name-bvdb.jpg
    +asmith.jpg
    +adamsmith.jpg
    +adamsmith2.jpg

    Use two or more digits to distinguish sequential files with the same description

    • Start number with a dash as a delimiter.
    • Add a zero to single digit numbers, e.g. '01' instead of '1'.
    • Numbers may also be placed before the description if needed. A dash will still be used as delimiter with the description.

    Right:

    description-01.jpg
    +description-02.jpg
    +description-03.jpg
    +description-04.jpg
    +
    +01-description.jpg
    +02-description.jpg
    +03-description.jpg
    +04-description.jpg
    description-01.jpg
    +description-02.jpg
    +description-03.jpg
    +description-04.jpg
    +
    +01-description.jpg
    +02-description.jpg
    +03-description.jpg
    +04-description.jpg

    Keep dates or date ranges compact and start with year

    • Write dates without delimiters.
    • Always use four digits for years, two digits for months and two digits for days.
    • Start with year, then month, and end with day if available: yyyymmdd, yyyymm, or yyyy. This makes sure similar file names are sorted by date when sorted alphabetically.
    • Use a double dash to separate two dates describing an interval: yyyy--yyyy. Start with the earliest date.

    Right:

    description-20150401.php
    +description-201504.php
    +description-2015.php
    +description-2000--2010.php
    description-20150401.php
    +description-201504.php
    +description-2015.php
    +description-2000--2010.php

    See 'ISO 8601' for further reading.

    Use special modifiers for target devices, image sizes or media queries, and pixel densities.

    Modifiers are inspired by Apple iOS naming conventions. There are some differences. Apple uses '@'as a delimiter for the section indicating higher resolution images, for example '@2x' for retina images. Because '@' is a reserved character and can create problems, we use Bourbon's convention: an underscore. Also, Apple uses a tilde (~) as a delimiter for a section indicating specific devices. Because also a tilde can create problems, we suggest to simply use a dash.

    • Order should be: (1) target device or media query, (2) size, (3) pixel density.
    • Start target device or media queries with a dash (-) as delimiter.
    • Start image sizes with a dash (-) as delimiter.
    • Start pixel density with an underscore (_) as delimiter, for example '_2x' or '_3x'.
    • When only a width or height is available or applicable, add a 'w' for width or 'h' for height directly after the the amount of pixels.
    • When both measurements are available, do not add a 'w' or 'h' and separate the width and height with an 'x'.
    • When both the width and height should not exceed a dimension but the images should keep the original aspect ratio, add a 'max' (maximum) after the amount of pixels.

    Right:

    description_2x.jpg
    +description-lap.jpg
    +description-desk.jpg
    +description-lap_2x.jpg
    +description-palm-1024w_2x.jpg
    +description-iphone5-568h_2x.jpg
    +description-palm-1024x768_2x.jpg
    +description-40max.jpg
    description_2x.jpg
    +description-lap.jpg
    +description-desk.jpg
    +description-lap_2x.jpg
    +description-palm-1024w_2x.jpg
    +description-iphone5-568h_2x.jpg
    +description-palm-1024x768_2x.jpg
    +description-40max.jpg

    Use version numbers if available

    • Start version with a dash (-) as delimiter.
    • Use periods (.) to separate point releases.
    • Always add trailing zeros to major releases, e.g. '2.0' instead of '2'.
    • Types, such as 'a' (alpha), 'b' (beta), 'rc1' (release candidate 1) can be added without delimiters.

    Right:

    description-0.5.js
    +description-1.0b.js
    +description-1.0rc1.js
    description-0.5.js
    +description-1.0b.js
    +description-1.0rc1.js

    Add status when needed

    • You can optionally add a file status such as 'draft' and 'published'.
    • Start status with a dash.

    Right:

    description-draft.md
    description-draft.md

    Add language code only when different languages are available

    • Use a period to separate the language code from the rest of the file name.
    • Use ISO 639-1, two-letter codes, for languages.
    • Only add languages when different languages are available.

    Right:

    description.nl.txt
    +description.en.txt
    description.nl.txt
    +description.en.txt

    Add file conditions just before the file extension

    • The file condition should be the last part, just before the file extension.
    • Use a period (.) to separate the condition from the rest of the file name.
    • Use periods (.) as a delimiter for different conditions.

    Right:

    description.min.js
    +description.custom1234.min.js
    description.min.js
    +description.custom1234.min.js

    Rewrite original file names not following conventions

    It is not preferred to keep file names in it's original format if it doesn't match your file name conventions. But in some cases it is easier to keep the file name untouched. Sometimes you want to easily replace a file with a newer one from the original source in the future.

    + \ No newline at end of file diff --git a/development/proxy4shell-terminal.html b/development/proxy4shell-terminal.html new file mode 100644 index 00000000..992f583e --- /dev/null +++ b/development/proxy4shell-terminal.html @@ -0,0 +1,121 @@ + + + + + + Proxies Configuration for Shells & Terminal | Toshiki's Note + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Proxies Configuration for Shells & Terminal

    Author:Anda Toshiki
    Published:2023-11-02
    Updated:2 minutes ago
    Words:2.8k
    Reading:17 min

    TL;DR

    This article discusses the configuration of proxies for shells and terminals. It explains the advantages of using proxy servers to bypass network restrictions and surveillance. The article provides examples of the challenges faced when accessing foreign services and shows how to set up a proxy tunnel using the curl command. It also provides scripts and instructions for setting up proxy switches in different shell environments, such as zsh, bash, and Windows CMD and PowerShell. The article concludes with additional information on proxy configurations for applications like ssh and tips for working with authentication procedures.

    1. Background

    Proxies or namely proxy servers are by far one of the most affordable or cost-effective option to establish a masked layer connection to bypass the network restrictions with the annoying surveillance tracked by a local network ISP as compared to a click-to-use VPN service, which generically requires more individual invest to protect themselves under the insecure internet environment nowadays. When a user resides within the environment where the local gateways of full, user-dominant open access towards the internet is censored or restricted with domestic network blockages by the country.

    while I adopt absolute subjective yet objective perspectives on the individual viewpoints towards the MIIT department of each country those of which applies the internet regulatory services within the national range for avoiding pitfalls on misleading information brought by cross-border influences; meanwhile regardlessly such measures are still facing controversial debates amongst publics that vastly limits the independent freedom rights, though advantages must not be underestimated, still.

    2. The Major Issue

    The majority of the issue still heavily preserves across the developmental fields which the layer of the blockage imposes limits on communicating with third-party, remote platforms such as Github or registries like NPM for frontend developments that stores key packages or components, as a requirement during a pre-built phase of a project. Most of the time foreign services becomes completely inaccessible or fortunately users could reach the services during a possible ISP maintenance downtime but normally the potentiality is mere, or hardly none yet the load speed before TTL connection expires are objectively slow, shortly before the origin site DNS being spoofed again. The unpleasant experiences with the networking somewhat affects interest on development reduces by high percentages or it even strand some awesome projects ran ashore ultimately.

    The following screenshots are a more direct representation to visualize the differences between the connection towards one of the most beloved search engine, Google with the following command via curl.

    sh
    curl -I google.com
    curl -I google.com

    The command is used to fetch the headers of a URL or web page. When you run "curl -I" followed by a URL, the command sends an HTTP HEAD request to the specified URL and retrieves the HTTP headers of the response. This allows you to view the information contained in the response headers without requesting and downloading the entire content of the page. The headers typically include details like the server information, content type, content length, status codes, and more.

    The following screenshot from terminal indicates the the final output of the package availability received without losses on a bare unmasked network environment, which returns FAIL in the final connection after a dry run fails 11s after when the TTL expires the connection fails.

    The next screenshot from terminal indicates a temporary proxy tunnel is established both in http and https protocol tunneled through a local proxy gateway at the local systemic IP address at 127.0.0.1 and exposes the proxy server at a mix of socks/https/http protocol port at 7890, just simply with the traditional export method by setting up in the nonce, the command is given as followed.

    sh
    export http_proxy=http://127.0.0.1:7890
    +export https_proxy=$http_proxy
    export http_proxy=http://127.0.0.1:7890
    +export https_proxy=$http_proxy

    And then we re-enter the same command with curl from above; surprisingly, the header responses returned TTP/1.1 200 OK, thus the conclusion drawn here is the proxy server we launched was successfully up and running with tunneled access towards foreign sites without restrictions! Hooray!

    ◎ Curl in action with successful response header from Google

    Since each proxy configuration might varies atop of the user preferred client, not including ShadowRocket, Clash, V2ray or other proprietary softwares that are licensed either behind a paywall to run with; or simply expensive to purchase a subscription; the proxy ports forwarded varies alongside the changes amongst clients. But the overall approach taken into the account still remains the same with the following traditional formats, the local IP of the machine (normally 127.0.0.1) followed after with the specified ports. In the scenario of the article is referenced as example, I chose Clash (in spite the entire Clash project repository as well as its affiliated forked projects are being taken down by anonymous reasons by either archiving the overall projects or simply shutting down due to possible legal actions or political reasons regarding the country of residency of various developers).

    shj
    # http protocal
    +http://127.0.0.1:7890
    +# https protocal
    +https://127.0.0.1:7890
    # http protocal
    +http://127.0.0.1:7890
    +# https protocal
    +https://127.0.0.1:7890

    2.1: Kill the Complexities; Unleash the Simplicity!

    But, the logic routes to the central question on: How can we simplify the course of action on setting up proxies without manually run export command every single time we wish to use? Below is a simple approach by aliasing a shortcut code to a proxy switch script amended towards your shell configuration profile that initializes on every session startups, in this case I uses zsh since it's integrated as the default shell on macOS since the release of macOS Catalina, yet it's one of my most familiar and favored shell when was using other OS as well.

    Though some people might use autosuggestion extensions as third-party shell features to automatically predict the command completion after a code piece is inputted such as zsh-autosuggestion plugin or fan of fish shell users has the native privilege of auto completions but I personally not fond of such featured integration since it might decelerate the load speed of an active session; I prefer stick tightly with original shell.

    sh
    # open your shell profile with an preferred editor
    +$ vim ~/.zshrc
    +
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +
    +# restart your terminal with a new session or reload the config
    +$ source ~/.zshrc
    # open your shell profile with an preferred editor
    +$ vim ~/.zshrc
    +
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +
    +# restart your terminal with a new session or reload the config
    +$ source ~/.zshrc

    The proxy essentially provides two shortcut command function defined with proxy_on and proxy_off. he proxy_on function sets the environment variables http_proxy and https_proxy to http://127.0.0.1:7890, which is the default proxy port of the traditional clash protocol, here is where you could replace the IP with other remote proxy servers or ports of other local proxies .Enabling a global proxy for the current terminal session. Meanwhile the proxy_off function unsets (removes) the http_proxy and https_proxy environment variables, effectively turning off the global proxy for the current terminal session. When any of the both executed, the indicator message will be echoed on the terminal, see the following screenshot in action.

    ◎ Enabling the shell session proxy with script

    After you reload your shell profile you can test out the scripted command yourself. To test whether the proxy has a successful setup after the proxy has been switched on, run echo $http_proxy or https_proxy with a dollar sign in front of the alias as an indicator for environmental variable, the third command as shown in the screenshot above, the command will simply print the configured variable value addressed to the specified alias. Contrarily, if your terminal returns the following resultant,

    sh
    $ proxy_on
    +zsh: command not found: proxy_on
    $ proxy_on
    +zsh: command not found: proxy_on

    Then you will have to distinguish the exact shell you are currently on, the hereinafter content are mainly targeted towards novice learners whom are unable to track the shell types or configuration on particular operating systems. The configuration file for each shell varies their file names as well the location of storage; while Mac users could directly apply changes based on the instruction provided above if your system if Catalina or above. To know what exactly the active shell running, run,

    sh
    $ echo $SHELL
    $ echo $SHELL

    The returned string text will be the name of the current active shell, the following is a list of the possible shell profile config name affiliated with each shell; most of the config profile files should be lied under the ~ or the root/home folder of each operating system with a dot in front of the file names are inferred as hidden file or directory in most of the Unix-like systems, such as macOS, Ubuntu, Debian and etc, but some of the config file such as fish shell could locate in an isolated config directory. The usual format of a config file is as followed,

    shell
    ~/.zshrc
    ~/.zshrc

    The following is a list of the most common shells with their possible profile file names that corresponded,

    • /bin/bash : .bash_profile or .bashrc
    • /bin/zsh : .zprofile or .zshrc
    • /bin/fish: ~/.config/fish/config

    Still, the location might still varies, users might have to perform individual research to precisely locate their configuration file location, which is out of my jurisdiction of concerns (it's just evident action of procrastination and laziness, my apologies if none of the ones above fits your demand) ;).

    For Unix-like users, after you have specified your shell as well as your config file name and locations, copy the following code chunk as command and paste it back into your terminal and run to apply permanent changes to the configuration.

    sh
    cat >> ~/.zshrc << EOF
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +EOF
    cat >> ~/.zshrc << EOF
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +EOF

    The script above will write-in and install the proxy switch script and save the the content to the very end of the file. As a kindly reminder, if your shell is not zsh make sure to replace the string after cat >> to the actual path of your profile as well as your proxy server IP and port to the actual functioning details to your own demand; then ultimately, don't for get to reinitialize the shell by close and reopen the terminal or simply sourcing the config,

    sh
    source ~/.zshrc
    source ~/.zshrc

    To check whether the proxy script has taken its effect to the current session, don't forget to rerun the same echo command indicated as above. And up until here, the script has been properly installed and operatable as a charm, if your's still does not take any effect, go through the process again and read carefully through the documentation.

    3: To All Windows Users

    The documentation above are mainly targeted towards macOS & Linux users, to setup local proxy with Windows machines there is a complete different approach if you are more comfortably working with Powershells and CMD, since I disused windows less and less frequently by the time I decided to upgrade my device to macOS; even if I did use Windows my primary choice of developmental environment is still Linux by the native support of WSL with enhanced Ubuntu version in a virtual environment; the following commands are only done from my prior researches, I do not fully guarantee the usability of the commands, please use them at your own risks if any unexpected errors not only including system crashes or other affiliated damages, I do not relate responsibility to any of those presented.

    Simple concluding, abandon proprietary software, fall in the hug of open source; Linux even if most of the users might feel overwhelming when getting started with the system first :). Alright, enough with off-topic talkings, let's jump right in the process.

    3.1: CMD

    cmd
    set http_proxy=http://127.0.0.1:7890
    +set https_proxy=http://127.0.0.1:7890
    set http_proxy=http://127.0.0.1:7890
    +set https_proxy=http://127.0.0.1:7890

    The commands are basically the same to Unix but the major difference is the amend commands in Windows are set instead of export. Once again I haven't personally tested the command, thus only use them as a reference. And whenever you wish to unset the global proxy for the session just simply run the set proxy command again but without any proxy server details.

    cmd
    set http_proxy=
    +set https_proxy=
    set http_proxy=
    +set https_proxy=

    3.2: PowerShell

    Alike CMD, the string after are exactly the same but the setup prefix command differentiates,

    powershell
    $env:http_proxy="http://127.0.0.1:1080"
    +$env:https_proxy="http://127.0.0.1:1080"
    $env:http_proxy="http://127.0.0.1:1080"
    +$env:https_proxy="http://127.0.0.1:1080"

    And to revert to the default proxy setting, execute the following command to unset both the http and https proxy.

    powershell
    $env:http_proxy=""
    +$env:https_proxy=""
    $env:http_proxy=""
    +$env:https_proxy=""

    4: Extended Trivia on Proxy

    Sometimes a proxy server may require an authentication procedure involving passcode for accessing before establishing a secure connection to interact with the server itself. From the partial article above we only discussed on a simple local proxy server setup including a host IP with its forwarded port gateways; but when facing the scenario described for a net connection, we will need a bit more complex method when working in the CLI environment.

    Before we start, quoting from one of the answer from AskUbuntu, resolving the misconception on the difference between terminal application and the net utilities falls underly,

    Terminal is not net application. Maybe is better to say, in your case, terminal is container for net application like ssh, telnet, lftp, wget, lynx ...

    A terminal provides a command-line interface that allows users to send commands and receive responses from network applications, facilitating communication and control over a network connection. It acts as a mediator between the user and the network applications, enabling the user to send instructions and receive information, but not a proxy client.

    Done with the technical talkings, now let's dive into the actual configuration process of the shell. Other than simply inputting a host IP and a port followed, the following formats are the default configuration for a proxy server with HTTP connection protocol, follow the exact same process as described based on your shell type, modify the fields with the following,

    shell
    export http_proxy=http://username:password@proxyhost:port/
    +export ftp_proxy=http://username:password@proxyhost:port/
    +export telnet_proxy=http://username:password@proxyhost:port/
    export http_proxy=http://username:password@proxyhost:port/
    +export ftp_proxy=http://username:password@proxyhost:port/
    +export telnet_proxy=http://username:password@proxyhost:port/

    Another approach suggested by the same user whom provided the answer on AskUbuntu for all Ubuntu users, edit the proxy configuration at the root of your machine as follows,

    sh
    sudo -H vim /etc/profile.d/proxy.sh
    sudo -H vim /etc/profile.d/proxy.sh

    And add the exported proxy members aligning the format as above, then save and reinitialize the environment, viola. The patches edited are mainly targeted for incorporating with wget, ftp, lftp, telnet in terminal.

    When working with ssh instance over a proxy, a different approach has to be taken since SSH library does not natively support SOCKS5 client, user will have to pass a ProxyCommand option as a workaround to apply proxied connection, below is an instance of socat,

    sh
    ssh -o ProxyCommand='socat - SOCKS4A:myproxy:%h:%p,socksuser=nobody' user@host
    ssh -o ProxyCommand='socat - SOCKS4A:myproxy:%h:%p,socksuser=nobody' user@host

    The proxyCommand option allows user to integrate socat as an intermediary mediator to establish connection above a proxy. Other alternatives like tsocks are as well viable to transparently use SOCKS for TCP traffic, Exemplifying running SOCKS5 over socat2,

    bash
    ssh -o ProxyCommand='socat - "SOCKS5:%h:%p|tcp:myproxy:1080"' user@host
    ssh -o ProxyCommand='socat - "SOCKS5:%h:%p|tcp:myproxy:1080"' user@host

    Further, socat2 for HTTP Proxy CONNECT method,

    bash
    ssh -o ProxyCommand='socat - "PROXY:%h:%p|tcp:myproxy:80"' user@host
    ssh -o ProxyCommand='socat - "PROXY:%h:%p|tcp:myproxy:80"' user@host
    + + + + \ No newline at end of file diff --git a/development/rclone-for-r2.html b/development/rclone-for-r2.html index 92d654ca..a3bdde56 100644 --- a/development/rclone-for-r2.html +++ b/development/rclone-for-r2.html @@ -5,15 +5,15 @@ Configure rclone for R2 | Toshiki's Note - + - + - + - + @@ -36,62 +36,62 @@ -
    Skip to content

    Configure rclone for R2

    Author:Anda Toshiki
    Updated:4 minutes ago
    Words:336
    Reading:2 min

    Example of how to configure rclone to use R2.

    You must generate an Access Key before getting started. All examples will utilize access_key_id and access_key_secret variables which represent the Access Key ID and Secret Access Key values you generated.

    With rclone installed, you may run rclone config to configure a new S3 storage provider. You will be prompted with a series of questions for the new prvider details.

    If you have already configured rclone in the past, you may run rclone config file to print the location of your rclone configuration file:

    bash
    $ rclone config file
    -# Configuration file is stored at:
    -# ~/.config/rclone/rclone.conf
    $ rclone config file
    -# Configuration file is stored at:
    -# ~/.config/rclone/rclone.conf

    Then use an editor (nano or vim, for example) to add or edit the new provider. This example assumes you are adding a new r2demo provider:

    bash
    [r2]
    -type = s3
    -provider = Cloudflare
    -access_key_id = abc123 # Your access_key_id
    -secret_access_key = xyz456 # Your access_key_secret
    -endpoint = https://<accountid>.r2.cloudflarestorage.com
    -acl = private
    [r2]
    -type = s3
    -provider = Cloudflare
    -access_key_id = abc123 # Your access_key_id
    -secret_access_key = xyz456 # Your access_key_secret
    -endpoint = https://<accountid>.r2.cloudflarestorage.com
    -acl = private

    You may then use the new rclone provider for any of your normal workflows.

    List buckets & objects

    The rclone tree command can be used to list the contents of the remote, in this case Cloudflare R2.

    bash
    $ rclone tree r2demo:
    -# /
    -# ├── user-uploads
    -# │   └── foobar.png
    -# └── my-bucket-name
    -#     ├── cat.png
    -#     └── todos.txt
    +    
    Skip to content

    Configure rclone for R2

    Author:Anda Toshiki
    Updated:2 minutes ago
    Words:336
    Reading:2 min

    Example of how to configure rclone to use R2.

    You must generate an Access Key before getting started. All examples will utilize access_key_id and access_key_secret variables which represent the Access Key ID and Secret Access Key values you generated.

    With rclone installed, you may run rclone config to configure a new S3 storage provider. You will be prompted with a series of questions for the new prvider details.

    If you have already configured rclone in the past, you may run rclone config file to print the location of your rclone configuration file:

    bash
    $ rclone config file
    +# Configuration file is stored at:
    +# ~/.config/rclone/rclone.conf
    $ rclone config file
    +# Configuration file is stored at:
    +# ~/.config/rclone/rclone.conf

    Then use an editor (nano or vim, for example) to add or edit the new provider. This example assumes you are adding a new r2demo provider:

    bash
    [r2]
    +type = s3
    +provider = Cloudflare
    +access_key_id = abc123 # Your access_key_id
    +secret_access_key = xyz456 # Your access_key_secret
    +endpoint = https://<accountid>.r2.cloudflarestorage.com
    +acl = private
    [r2]
    +type = s3
    +provider = Cloudflare
    +access_key_id = abc123 # Your access_key_id
    +secret_access_key = xyz456 # Your access_key_secret
    +endpoint = https://<accountid>.r2.cloudflarestorage.com
    +acl = private

    You may then use the new rclone provider for any of your normal workflows.

    List buckets & objects

    The rclone tree command can be used to list the contents of the remote, in this case Cloudflare R2.

    bash
    $ rclone tree r2demo:
    +# /
    +# ├── user-uploads
    +# │   └── foobar.png
    +# └── my-bucket-name
    +#     ├── cat.png
    +#     └── todos.txt
     
    -$ rclone tree r2demo:my-bucket-name
    -# /
    -# ├── cat.png
    -# └── todos.txt
    $ rclone tree r2demo:
    -# /
    -# ├── user-uploads
    -# │   └── foobar.png
    -# └── my-bucket-name
    -#     ├── cat.png
    -#     └── todos.txt
    +$ rclone tree r2demo:my-bucket-name
    +# /
    +# ├── cat.png
    +# └── todos.txt
    $ rclone tree r2demo:
    +# /
    +# ├── user-uploads
    +# │   └── foobar.png
    +# └── my-bucket-name
    +#     ├── cat.png
    +#     └── todos.txt
     
    -$ rclone tree r2demo:my-bucket-name
    -# /
    -# ├── cat.png
    -# └── todos.txt

    Upload and retrieve objects

    The rclone copy command can be used to upload objects to an R2 bucket and vice versa - this allows you to upload files up to the 5 TB maximum object size that R2 supports.

    bash
    # Upload dog.txt to the user-uploads bucket
    -$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    -$ rclone tree r2demo:user-uploads
    -# /
    -# ├── foobar.png
    -# └── dog.txt
    +$ rclone tree r2demo:my-bucket-name
    +# /
    +# ├── cat.png
    +# └── todos.txt

    Upload and retrieve objects

    The rclone copy command can be used to upload objects to an R2 bucket and vice versa - this allows you to upload files up to the 5 TB maximum object size that R2 supports.

    bash
    # Upload dog.txt to the user-uploads bucket
    +$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    +$ rclone tree r2demo:user-uploads
    +# /
    +# ├── foobar.png
    +# └── dog.txt
     
    -# Download dog.txt from the user-uploads bucket
    -$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    # Upload dog.txt to the user-uploads bucket
    -$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    -$ rclone tree r2demo:user-uploads
    -# /
    -# ├── foobar.png
    -# └── dog.txt
    +# Download dog.txt from the user-uploads bucket
    +$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    # Upload dog.txt to the user-uploads bucket
    +$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    +$ rclone tree r2demo:user-uploads
    +# /
    +# ├── foobar.png
    +# └── dog.txt
     
    -# Download dog.txt from the user-uploads bucket
    -$ rclone copy r2demo:user-uploads/dog.txt dog.txt

    Generate presigned URLs

    You can also generate presigned links which allow you to share public access to a file temporarily using the rclone link command.

    - +# Download dog.txt from the user-uploads bucket +$ rclone copy r2demo:user-uploads/dog.txt dog.txt

    Generate presigned URLs

    You can also generate presigned links which allow you to share public access to a file temporarily using the rclone link command.

    + \ No newline at end of file diff --git a/feed.xml b/feed.xml index a111dddc..eec69eb2 100644 --- a/feed.xml +++ b/feed.xml @@ -4,7 +4,7 @@ toshiki-notebook https://note.toshiki.dev Toshiki's web notebook served via Vitepress! - Fri, 22 Sep 2023 10:17:15 GMT + Fri, 03 Nov 2023 22:54:27 GMT https://validator.w3.org/feed/docs/rss2.html https://github.com/jpmonette/feed en-US @@ -3553,67 +3553,67 @@ M834 80h400000v40h-400000z'/>

    1: Installation

    Before you start using this plugin, make sure you have already installed the default markdown-it parser; if not, please run the following command or refer to the official markdown-it documentation.

    -
    sh
    $ npm install markdown-it --save
    $ npm install markdown-it --save
    +
    sh
    $ npm install markdown-it --save
    $ npm install markdown-it --save

    First install package with your preferred package manager (npm, yarn, pnpm), or include javascript before the closing </body> for markdown-it-katex's core utils to be loaded for the static page.

    -
    -
    sh
    $ npm install -D @andatoshiki/markdown-it-katex
    $ npm install -D @andatoshiki/markdown-it-katex
    -
    sh
    $ yarn add --dev @andatoshiki/markdown-it-katex
    $ yarn add --dev @andatoshiki/markdown-it-katex
    -
    sh
    $ pnpm add -D @andatoshiki/markdown-it-katex
    $ pnpm add -D @andatoshiki/markdown-it-katex
    -
    html
    <!-- your other body contents ... -->
    -    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    -</body>
    <!-- your other body contents ... -->
    -    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    -</body>
    +
    +
    sh
    $ npm install -D @andatoshiki/markdown-it-katex
    $ npm install -D @andatoshiki/markdown-it-katex
    +
    sh
    $ yarn add --dev @andatoshiki/markdown-it-katex
    $ yarn add --dev @andatoshiki/markdown-it-katex
    +
    sh
    $ pnpm add -D @andatoshiki/markdown-it-katex
    $ pnpm add -D @andatoshiki/markdown-it-katex
    +
    html
    <!-- your other body contents ... -->
    +    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    +</body>
    <!-- your other body contents ... -->
    +    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    +</body>

    Including KaTeX CSS is necessary in the way you are convenient with, either link the stylesheet from a third party CDN into the local HTML <head> tag or import it into a currently linked CSS stylesheets to enable styles for KaTeX globally as follows,

    Or, you could clone or download the entire repository source of KaTeX and self load the fonts/styles/scripts locally, but if you prefer loading from third-party CDN with faster load speed when deployed to save your server resources, the following CDN links might be your choice, you can always switch to other platforms based on your need.

    -
    -
    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    -
    html
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    -
    html
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    -
    html
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    -
    html
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    -
    scss
    // ... your other styles
    -@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
    // ... your other styles
    -@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
    +
    +
    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    +
    html
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    +
    html
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    +
    html
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    +
    html
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    +
    scss
    // ... your other styles
    +@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
    // ... your other styles
    +@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';

    If you are using the default markdown-it parser, I personally recommend that you use the GitHub markdown CSS (github-markdown-css) for styling your HTML output with a similar style replica of GitHub's markdown styling to your familiarity.

    -
    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
    +
    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />

    This forked project maintained by Anda Toshiki comes with the update of KaTeX components with higher style version support (this documentation uses KaTeX version 16.0, without hassels), later versions may works, but no guarantees are given by the developers, if you are not obsessed with the latest released version, 16.0 may fits your need for loading KaTeX on a personal blog site or small educational sites; yet it should work fully functionally.

    Warning

    Since this project is a fork of the original markdown-it-katex project that hasn't been receiving any active updates of its code source for years, the latest katex style version supported is somewhere around ver. 0.9.0 which clearly is outdated and results in broken styles with overflowing and other potential bug presents.

    2: Usage

    RTo render equations, you need to include the markdown-it-katex plugin in the markdown-it components in your JavaScript or TypeScript file as follows,

    -
    -
    js
    var md = require('markdown-it')(),
    -    mk = require('andatoshiki/markdown-it-katex')
    +
    +
    js
    var md = require('markdown-it')(),
    +    mk = require('andatoshiki/markdown-it-katex')
     
    -md.use(mk)
    +md.use(mk)
     
    -// double backslash is required for javascript strings, but not html input
    -var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    var md = require('markdown-it')(),
    -    mk = require('andatoshiki/markdown-it-katex')
    +// double backslash is required for javascript strings, but not html input
    +var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    var md = require('markdown-it')(),
    +    mk = require('andatoshiki/markdown-it-katex')
     
    -md.use(mk)
    +md.use(mk)
     
    -// double backslash is required for javascript strings, but not html input
    -var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    -
    ts
    import * as mk from 'markdown-it-katex'
    -import * as MarkdownIt from '@andatoshiki/markdown-it'
    +// double backslash is required for javascript strings, but not html input
    +var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    +
    ts
    import * as mk from 'markdown-it-katex'
    +import * as MarkdownIt from '@andatoshiki/markdown-it'
     
    -const md = new MarkdownIt()
    -md.use(mk)
    +const md = new MarkdownIt()
    +md.use(mk)
     
    -// double backslash is not required for TypeScript strings or template literals
    -const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    import * as mk from 'markdown-it-katex'
    -import * as MarkdownIt from '@andatoshiki/markdown-it'
    +// double backslash is not required for TypeScript strings or template literals
    +const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    import * as mk from 'markdown-it-katex'
    +import * as MarkdownIt from '@andatoshiki/markdown-it'
     
    -const md = new MarkdownIt()
    -md.use(mk)
    +const md = new MarkdownIt()
    +md.use(mk)
     
    -// double backslash is not required for TypeScript strings or template literals
    -const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    +// double backslash is not required for TypeScript strings or template literals +const result = md.render('# Math Rulez! \n $\\sqrt{3x-1}+(1+x)^2$')

    3: Configuration

    The following list of variable are the customizable components of markdown-it-katex, adjust to your needs,

    @@ -3622,11 +3622,11 @@ M834 80h400000v40h-400000z'/>

    Solution

  • blockClass: Class added to KaTeX block.
  • Apply any other KaTeX options if needed as a regard to the docs
  • -
    js
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
    +
    js
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })

    4: Examples

    4.1: Inline math

    To render your LaTeX equations inline, enclose them with a single dollar sign $ on each side of the equation as follows,

    -
    tex
    $\sqrt{3x-1}+(1+x)^2$
    $\sqrt{3x-1}+(1+x)^2$
    +
    tex
    $\sqrt{3x-1}+(1+x)^2$
    $\sqrt{3x-1}+(1+x)^2$

    rendered output equation as follows, 3x1+(1+x)2\sqrt{3x-1}+(1+x)^2.

    4.2: Blocked math

    To render blocks, use double dollar sign ($$). This mode utilizes larger symbols and centers the result as a block displayed as a <div> block in HTML output, as follows,

    -
    tex
    $$
    -\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
    -= \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
    -$$
    $$
    -\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
    -= \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
    -$$
    +
    tex
    $$
    +\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
    += \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
    +$$
    $$
    +\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
    += \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
    +$$

    the above block equation renders the LaTeX equation as a block with output as follows,

    rωr(yωω)=(yωω){(logy)r+i=1r(1)Ir(ri+1)(logy)riωi}\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right) = \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\} @@ -3672,67 +3672,67 @@ M834 80h400000v40h-400000z'/>

    1: Installation

    Before you start using this plugin, make sure you have already installed the default markdown-it parser; if not, please run the following command or refer to the official markdown-it documentation.

    -
    sh
    $ npm install markdown-it --save
    $ npm install markdown-it --save
    +
    sh
    $ npm install markdown-it --save
    $ npm install markdown-it --save

    First install package with your preferred package manager (npm, yarn, pnpm), or include javascript before the closing </body> for markdown-it-katex's core utils to be loaded for the static page.

    -
    -
    sh
    $ npm install -D @andatoshiki/markdown-it-katex
    $ npm install -D @andatoshiki/markdown-it-katex
    -
    sh
    $ yarn add --dev @andatoshiki/markdown-it-katex
    $ yarn add --dev @andatoshiki/markdown-it-katex
    -
    sh
    $ pnpm add -D @andatoshiki/markdown-it-katex
    $ pnpm add -D @andatoshiki/markdown-it-katex
    -
    html
    <!-- your other body contents ... -->
    -    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    -</body>
    <!-- your other body contents ... -->
    -    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    -</body>
    +
    +
    sh
    $ npm install -D @andatoshiki/markdown-it-katex
    $ npm install -D @andatoshiki/markdown-it-katex
    +
    sh
    $ yarn add --dev @andatoshiki/markdown-it-katex
    $ yarn add --dev @andatoshiki/markdown-it-katex
    +
    sh
    $ pnpm add -D @andatoshiki/markdown-it-katex
    $ pnpm add -D @andatoshiki/markdown-it-katex
    +
    html
    <!-- your other body contents ... -->
    +    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    +</body>
    <!-- your other body contents ... -->
    +    <script src="https://unpkg.com/@andatoshiki/markdown-it-katex@0.0.3/markdown-it-katex.min.js"></script>
    +</body>

    Including KaTeX CSS is necessary in the way you are convenient with, either link the stylesheet from a third party CDN into the local HTML <head> tag or import it into a currently linked CSS stylesheets to enable styles for KaTeX globally as follows,

    Or, you could clone or download the entire repository source of KaTeX and self load the fonts/styles/scripts locally, but if you prefer loading from third-party CDN with faster load speed when deployed to save your server resources, the following CDN links might be your choice, you can always switch to other platforms based on your need.

    -
    -
    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    -
    html
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    -
    html
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    -
    html
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    -
    html
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    -
    scss
    // ... your other styles
    -@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
    // ... your other styles
    -@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
    +
    +
    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    +
    html
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    +
    html
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" />
    +
    html
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.0/katex.min.css" />
    +
    html
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    <link rel="stylesheet" href="https://unpkg.com/katex@0.16.0/dist/katex.min.css" />
    +
    scss
    // ... your other styles
    +@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';
    // ... your other styles
    +@import 'https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css';

    If you are using the default markdown-it parser, I personally recommend that you use the GitHub markdown CSS (github-markdown-css) for styling your HTML output with a similar style replica of GitHub's markdown styling to your familiarity.

    -
    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
    +
    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.2.0/github-markdown.min.css" />

    This forked project maintained by Anda Toshiki comes with the update of KaTeX components with higher style version support (this documentation uses KaTeX version 16.0, without hassels), later versions may works, but no guarantees are given by the developers, if you are not obsessed with the latest released version, 16.0 may fits your need for loading KaTeX on a personal blog site or small educational sites; yet it should work fully functionally.

    Warning

    Since this project is a fork of the original markdown-it-katex project that hasn't been receiving any active updates of its code source for years, the latest katex style version supported is somewhere around ver. 0.9.0 which clearly is outdated and results in broken styles with overflowing and other potential bug presents.

    2: Usage

    RTo render equations, you need to include the markdown-it-katex plugin in the markdown-it components in your JavaScript or TypeScript file as follows,

    -
    -
    js
    var md = require('markdown-it')(),
    -    mk = require('andatoshiki/markdown-it-katex')
    +
    +
    js
    var md = require('markdown-it')(),
    +    mk = require('andatoshiki/markdown-it-katex')
     
    -md.use(mk)
    +md.use(mk)
     
    -// double backslash is required for javascript strings, but not html input
    -var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    var md = require('markdown-it')(),
    -    mk = require('andatoshiki/markdown-it-katex')
    +// double backslash is required for javascript strings, but not html input
    +var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    var md = require('markdown-it')(),
    +    mk = require('andatoshiki/markdown-it-katex')
     
    -md.use(mk)
    +md.use(mk)
     
    -// double backslash is required for javascript strings, but not html input
    -var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    -
    ts
    import * as mk from 'markdown-it-katex'
    -import * as MarkdownIt from '@andatoshiki/markdown-it'
    +// double backslash is required for javascript strings, but not html input
    +var result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    +
    ts
    import * as mk from 'markdown-it-katex'
    +import * as MarkdownIt from '@andatoshiki/markdown-it'
     
    -const md = new MarkdownIt()
    -md.use(mk)
    +const md = new MarkdownIt()
    +md.use(mk)
     
    -// double backslash is not required for TypeScript strings or template literals
    -const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    import * as mk from 'markdown-it-katex'
    -import * as MarkdownIt from '@andatoshiki/markdown-it'
    +// double backslash is not required for TypeScript strings or template literals
    +const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    import * as mk from 'markdown-it-katex'
    +import * as MarkdownIt from '@andatoshiki/markdown-it'
     
    -const md = new MarkdownIt()
    -md.use(mk)
    +const md = new MarkdownIt()
    +md.use(mk)
     
    -// double backslash is not required for TypeScript strings or template literals
    -const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$')
    +// double backslash is not required for TypeScript strings or template literals +const result = md.render('# Math Rulez! \n $\\sqrt{3x-1}+(1+x)^2$')

    3: Configuration

    The following list of variable are the customizable components of markdown-it-katex, adjust to your needs,

    @@ -3741,11 +3741,11 @@ M834 80h400000v40h-400000z'/>
  • blockClass: Class added to KaTeX block.
  • Apply any other KaTeX options if needed as a regard to the docs
  • -
    js
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
    +
    js
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })
    md.use(mk, { blockClass: 'math-block', errorColor: ' #cc0000' })

    4: Examples

    4.1: Inline math

    To render your LaTeX equations inline, enclose them with a single dollar sign $ on each side of the equation as follows,

    -
    tex
    $\sqrt{3x-1}+(1+x)^2$
    $\sqrt{3x-1}+(1+x)^2$
    +
    tex
    $\sqrt{3x-1}+(1+x)^2$
    $\sqrt{3x-1}+(1+x)^2$

    rendered output equation as follows, 3x1+(1+x)2\sqrt{3x-1}+(1+x)^2.

    4.2: Blocked math

    To render blocks, use double dollar sign ($$). This mode utilizes larger symbols and centers the result as a block displayed as a <div> block in HTML output, as follows,

    -
    tex
    $$
    -\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
    -= \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
    -$$
    $$
    -\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
    -= \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
    -$$
    +
    tex
    $$
    +\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
    += \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
    +$$
    $$
    +\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right)
    += \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\}
    +$$

    the above block equation renders the LaTeX equation as a block with output as follows,

    rωr(yωω)=(yωω){(logy)r+i=1r(1)Ir(ri+1)(logy)riωi}\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right) = \left(\frac {y^{\omega}} {\omega}\right) \left\{(\log y)^r + \sum_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right\} @@ -19959,11 +19959,11 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

    The above situation is undoubtedly annoying for user experiences while reading documentation, consider at what scenarios users have to scroll, scroll and scroll only for viewing a single long-blocked equation, who would want to read such a text, right? But don't worry we have a simple fix for this situation via by several line of css.

    1.2: Temporary solution

    If you happened to search over KaTeX's official repo issue tracker on GitHub, there are several user-made css tweaks hack already, the fix is simple by adjusting the overflows of both x and y axes of the KaTeX render <div> blocks. The katex-display > .katex selector targets the child element of the .katex-display class that has the .katex class. This is the element that contains the KaTeX math expression. The first block of styles is mostly concerned with making sure that the KaTeX expression doesn't overflow its container and can be scrolled horizontally if needed. The second block of styles sets the font and line-height for the KaTeX expression and makes sure that its text is properly indented.

    -

    +

    @preview

    But, the issue here is, the overflowing issue is resolved on the webpage, but the style itself left with a slight whitish "box" at the crossing corner of both horizontal as well as vertical scrollbar tracks, this might not be so explicit in the light mode of the webpage, but when it turns to dark mode, the box become annoying. Some people might say it's an easy tweak via setting the display property of the "box" element to display: none; to directly remove the box out of the page, this is a smart approach; however, while the box is gone, the two crossing tracks is going to form an untouched invisible box again against two bars without color. Thus, neither ways seems to perfectly solve the problem.

    1.3: Finding solution

    After running a quick research on Google, I found a simple hack tweak used in a theme of VuePress, vuepress-theme-hope on GitHub, the theme both integrate with KaTeX and MathJax for math supports.

    -

    +

    @preview

    Under the styles directory of the repository, several line of scss styles came across my eyes,

    KaTeX tweak fix styles in theme
    ◎ KaTeX tweak fix styles in theme

    this scss lines only add a horizontal trackbar at the bottom of each overflowing equation while maximizing the vertical height of the equation, when user is on a small screened device as follows,

    @@ -19972,71 +19972,71 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

    1.4: Solution

    If you are running a documentation site like this version controlled via Node, especially VitePress without native scss supports, your fix would be installing scss support globally across the project, then add the scss styles and finally import the stylesheets to take effect globally.

    Install global scss support using your favored package manager.

    -
    -
    sh
    $ npm install -D scss
    $ npm install -D scss
    -
    sh
    $ yarn add --dev scss
    $ yarn add --dev scss
    -
    sh
    $ pnpm add -D scss
    $ pnpm add -D scss
    +
    +
    sh
    $ npm install -D scss
    $ npm install -D scss
    +
    sh
    $ yarn add --dev scss
    $ yarn add --dev scss
    +
    sh
    $ pnpm add -D scss
    $ pnpm add -D scss

    Then in your scss stylesheets, add the following and link or import them to your global styles, you should be off to go with a complete fix-up for KaTeX.

    -
    scss
    ...
    +
    scss
    ...
     
    -// katex responsiveness fix
    -.katex {
    -  font-size: 1.05em;
    -  direction: ltr;
    -}
    +// katex responsiveness fix
    +.katex {
    +  font-size: 1.05em;
    +  direction: ltr;
    +}
     
    -.katex-display {
    -  overflow: auto hidden;
    -  -webkit-overflow-scrolling: touch;
    -  padding-top: 0.2em;
    -  padding-bottom: 0.2em;
    +.katex-display {
    +  overflow: auto hidden;
    +  -webkit-overflow-scrolling: touch;
    +  padding-top: 0.2em;
    +  padding-bottom: 0.2em;
     
    -  &::-webkit-scrollbar {
    -    height: 3px;
    -  }
    +  &::-webkit-scrollbar {
    +    height: 3px;
    +  }
     
    -  .katex {
    -    font-size: 1.21em;
    -  }
    -}
    +  .katex {
    +    font-size: 1.21em;
    +  }
    +}
     
    -.katex-error {
    -  color: #f00;
    -}
    -// katex responsiveness fix ends
    +.katex-error {
    +  color: #f00;
    +}
    +// katex responsiveness fix ends
     
    -...
    ...
    +...
    ...
     
    -// katex responsiveness fix
    -.katex {
    -  font-size: 1.05em;
    -  direction: ltr;
    -}
    +// katex responsiveness fix
    +.katex {
    +  font-size: 1.05em;
    +  direction: ltr;
    +}
     
    -.katex-display {
    -  overflow: auto hidden;
    -  -webkit-overflow-scrolling: touch;
    -  padding-top: 0.2em;
    -  padding-bottom: 0.2em;
    +.katex-display {
    +  overflow: auto hidden;
    +  -webkit-overflow-scrolling: touch;
    +  padding-top: 0.2em;
    +  padding-bottom: 0.2em;
     
    -  &::-webkit-scrollbar {
    -    height: 3px;
    -  }
    +  &::-webkit-scrollbar {
    +    height: 3px;
    +  }
     
    -  .katex {
    -    font-size: 1.21em;
    -  }
    -}
    +  .katex {
    +    font-size: 1.21em;
    +  }
    +}
     
    -.katex-error {
    -  color: #f00;
    -}
    -// katex responsiveness fix ends
    +.katex-error {
    +  color: #f00;
    +}
    +// katex responsiveness fix ends
     
    -...
    +...

    Next, import your styles globally to take effect,

    -
    scss
    @import '<your-scss-file>.scss';
    @import '<your-scss-file>.scss';
    +
    scss
    @import '<your-scss-file>.scss';
    @import '<your-scss-file>.scss';

    1.4.1: Fix Explanation

    The first section sets the base styles for all KaTeX elements by increasing the font size slightly and ensuring that the text direction is left to right.

    The second section of code targets the KaTeX display elements specifically. This section adds a bit of padding to the top and bottom of the display elements and sets overflow to auto hidden, which allows the content to scroll inside the container horizontally if it overflows the container's width. The -webkit-overflow-scrolling property is added to ensure smooth scrolling on mobile devices.

    @@ -20045,51 +20045,51 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

    1.5: What if I Don't Have SCSS?

    If you do not have native scss support for your site, such as a static HTML based documentation site or content management site builder such as Wiki.JS that works as an SaaS which only allows users to apply custom stylesheets within slots provided and make effects, you could use some scss to css converter online with options follows,

    to precompile from source scss into normal css styles and use them based on your needs, below are auto-generated compiled css, ONLY take it as reference, I do not guarantee the usability.

    -
    css
    .katex {
    -    font-size: 1.05em;
    -    direction: ltr;
    -}
    +
    css
    .katex {
    +    font-size: 1.05em;
    +    direction: ltr;
    +}
     
    -.katex-display {
    -    overflow: auto hidden;
    -    -webkit-overflow-scrolling: touch;
    -    padding-top: 0.2em;
    -    padding-bottom: 0.2em;
    -}
    -.katex-display::-webkit-scrollbar {
    -    height: 3px;
    -}
    -.katex-display .katex {
    -    font-size: 1.21em;
    -}
    +.katex-display {
    +    overflow: auto hidden;
    +    -webkit-overflow-scrolling: touch;
    +    padding-top: 0.2em;
    +    padding-bottom: 0.2em;
    +}
    +.katex-display::-webkit-scrollbar {
    +    height: 3px;
    +}
    +.katex-display .katex {
    +    font-size: 1.21em;
    +}
     
    -.katex-error {
    -    color: #f00;
    -}
    .katex {
    -    font-size: 1.05em;
    -    direction: ltr;
    -}
    +.katex-error {
    +    color: #f00;
    +}
    .katex {
    +    font-size: 1.05em;
    +    direction: ltr;
    +}
     
    -.katex-display {
    -    overflow: auto hidden;
    -    -webkit-overflow-scrolling: touch;
    -    padding-top: 0.2em;
    -    padding-bottom: 0.2em;
    -}
    -.katex-display::-webkit-scrollbar {
    -    height: 3px;
    -}
    -.katex-display .katex {
    -    font-size: 1.21em;
    -}
    +.katex-display {
    +    overflow: auto hidden;
    +    -webkit-overflow-scrolling: touch;
    +    padding-top: 0.2em;
    +    padding-bottom: 0.2em;
    +}
    +.katex-display::-webkit-scrollbar {
    +    height: 3px;
    +}
    +.katex-display .katex {
    +    font-size: 1.21em;
    +}
     
    -.katex-error {
    -    color: #f00;
    -}
    +.katex-error { + color: #f00; +}

    To be continued.

    Reference

      @@ -20108,11 +20108,11 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

      The above situation is undoubtedly annoying for user experiences while reading documentation, consider at what scenarios users have to scroll, scroll and scroll only for viewing a single long-blocked equation, who would want to read such a text, right? But don't worry we have a simple fix for this situation via by several line of css.

      1.2: Temporary solution

      If you happened to search over KaTeX's official repo issue tracker on GitHub, there are several user-made css tweaks hack already, the fix is simple by adjusting the overflows of both x and y axes of the KaTeX render <div> blocks. The katex-display > .katex selector targets the child element of the .katex-display class that has the .katex class. This is the element that contains the KaTeX math expression. The first block of styles is mostly concerned with making sure that the KaTeX expression doesn't overflow its container and can be scrolled horizontally if needed. The second block of styles sets the font and line-height for the KaTeX expression and makes sure that its text is properly indented.

      -

      +

      @preview

      But, the issue here is, the overflowing issue is resolved on the webpage, but the style itself left with a slight whitish "box" at the crossing corner of both horizontal as well as vertical scrollbar tracks, this might not be so explicit in the light mode of the webpage, but when it turns to dark mode, the box become annoying. Some people might say it's an easy tweak via setting the display property of the "box" element to display: none; to directly remove the box out of the page, this is a smart approach; however, while the box is gone, the two crossing tracks is going to form an untouched invisible box again against two bars without color. Thus, neither ways seems to perfectly solve the problem.

      1.3: Finding solution

      After running a quick research on Google, I found a simple hack tweak used in a theme of VuePress, vuepress-theme-hope on GitHub, the theme both integrate with KaTeX and MathJax for math supports.

      -

      +

      @preview

      Under the styles directory of the repository, several line of scss styles came across my eyes,

      KaTeX tweak fix styles in theme
      ◎ KaTeX tweak fix styles in theme

      this scss lines only add a horizontal trackbar at the bottom of each overflowing equation while maximizing the vertical height of the equation, when user is on a small screened device as follows,

      @@ -20121,71 +20121,71 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

      1.4: Solution

      If you are running a documentation site like this version controlled via Node, especially VitePress without native scss supports, your fix would be installing scss support globally across the project, then add the scss styles and finally import the stylesheets to take effect globally.

      Install global scss support using your favored package manager.

      -
      -
      sh
      $ npm install -D scss
      $ npm install -D scss
      -
      sh
      $ yarn add --dev scss
      $ yarn add --dev scss
      -
      sh
      $ pnpm add -D scss
      $ pnpm add -D scss
      +
      +
      sh
      $ npm install -D scss
      $ npm install -D scss
      +
      sh
      $ yarn add --dev scss
      $ yarn add --dev scss
      +
      sh
      $ pnpm add -D scss
      $ pnpm add -D scss

      Then in your scss stylesheets, add the following and link or import them to your global styles, you should be off to go with a complete fix-up for KaTeX.

      -
      scss
      ...
      +
      scss
      ...
       
      -// katex responsiveness fix
      -.katex {
      -  font-size: 1.05em;
      -  direction: ltr;
      -}
      +// katex responsiveness fix
      +.katex {
      +  font-size: 1.05em;
      +  direction: ltr;
      +}
       
      -.katex-display {
      -  overflow: auto hidden;
      -  -webkit-overflow-scrolling: touch;
      -  padding-top: 0.2em;
      -  padding-bottom: 0.2em;
      +.katex-display {
      +  overflow: auto hidden;
      +  -webkit-overflow-scrolling: touch;
      +  padding-top: 0.2em;
      +  padding-bottom: 0.2em;
       
      -  &::-webkit-scrollbar {
      -    height: 3px;
      -  }
      +  &::-webkit-scrollbar {
      +    height: 3px;
      +  }
       
      -  .katex {
      -    font-size: 1.21em;
      -  }
      -}
      +  .katex {
      +    font-size: 1.21em;
      +  }
      +}
       
      -.katex-error {
      -  color: #f00;
      -}
      -// katex responsiveness fix ends
      +.katex-error {
      +  color: #f00;
      +}
      +// katex responsiveness fix ends
       
      -...
      ...
      +...
      ...
       
      -// katex responsiveness fix
      -.katex {
      -  font-size: 1.05em;
      -  direction: ltr;
      -}
      +// katex responsiveness fix
      +.katex {
      +  font-size: 1.05em;
      +  direction: ltr;
      +}
       
      -.katex-display {
      -  overflow: auto hidden;
      -  -webkit-overflow-scrolling: touch;
      -  padding-top: 0.2em;
      -  padding-bottom: 0.2em;
      +.katex-display {
      +  overflow: auto hidden;
      +  -webkit-overflow-scrolling: touch;
      +  padding-top: 0.2em;
      +  padding-bottom: 0.2em;
       
      -  &::-webkit-scrollbar {
      -    height: 3px;
      -  }
      +  &::-webkit-scrollbar {
      +    height: 3px;
      +  }
       
      -  .katex {
      -    font-size: 1.21em;
      -  }
      -}
      +  .katex {
      +    font-size: 1.21em;
      +  }
      +}
       
      -.katex-error {
      -  color: #f00;
      -}
      -// katex responsiveness fix ends
      +.katex-error {
      +  color: #f00;
      +}
      +// katex responsiveness fix ends
       
      -...
      +...

      Next, import your styles globally to take effect,

      -
      scss
      @import '<your-scss-file>.scss';
      @import '<your-scss-file>.scss';
      +
      scss
      @import '<your-scss-file>.scss';
      @import '<your-scss-file>.scss';

      1.4.1: Fix Explanation

      The first section sets the base styles for all KaTeX elements by increasing the font size slightly and ensuring that the text direction is left to right.

      The second section of code targets the KaTeX display elements specifically. This section adds a bit of padding to the top and bottom of the display elements and sets overflow to auto hidden, which allows the content to scroll inside the container horizontally if it overflows the container's width. The -webkit-overflow-scrolling property is added to ensure smooth scrolling on mobile devices.

      @@ -20194,51 +20194,51 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

      1.5: What if I Don't Have SCSS?

      If you do not have native scss support for your site, such as a static HTML based documentation site or content management site builder such as Wiki.JS that works as an SaaS which only allows users to apply custom stylesheets within slots provided and make effects, you could use some scss to css converter online with options follows,

      to precompile from source scss into normal css styles and use them based on your needs, below are auto-generated compiled css, ONLY take it as reference, I do not guarantee the usability.

      -
      css
      .katex {
      -    font-size: 1.05em;
      -    direction: ltr;
      -}
      +
      css
      .katex {
      +    font-size: 1.05em;
      +    direction: ltr;
      +}
       
      -.katex-display {
      -    overflow: auto hidden;
      -    -webkit-overflow-scrolling: touch;
      -    padding-top: 0.2em;
      -    padding-bottom: 0.2em;
      -}
      -.katex-display::-webkit-scrollbar {
      -    height: 3px;
      -}
      -.katex-display .katex {
      -    font-size: 1.21em;
      -}
      +.katex-display {
      +    overflow: auto hidden;
      +    -webkit-overflow-scrolling: touch;
      +    padding-top: 0.2em;
      +    padding-bottom: 0.2em;
      +}
      +.katex-display::-webkit-scrollbar {
      +    height: 3px;
      +}
      +.katex-display .katex {
      +    font-size: 1.21em;
      +}
       
      -.katex-error {
      -    color: #f00;
      -}
      .katex {
      -    font-size: 1.05em;
      -    direction: ltr;
      -}
      +.katex-error {
      +    color: #f00;
      +}
      .katex {
      +    font-size: 1.05em;
      +    direction: ltr;
      +}
       
      -.katex-display {
      -    overflow: auto hidden;
      -    -webkit-overflow-scrolling: touch;
      -    padding-top: 0.2em;
      -    padding-bottom: 0.2em;
      -}
      -.katex-display::-webkit-scrollbar {
      -    height: 3px;
      -}
      -.katex-display .katex {
      -    font-size: 1.21em;
      -}
      +.katex-display {
      +    overflow: auto hidden;
      +    -webkit-overflow-scrolling: touch;
      +    padding-top: 0.2em;
      +    padding-bottom: 0.2em;
      +}
      +.katex-display::-webkit-scrollbar {
      +    height: 3px;
      +}
      +.katex-display .katex {
      +    font-size: 1.21em;
      +}
       
      -.katex-error {
      -    color: #f00;
      -}
      +.katex-error { + color: #f00; +}

      To be continued.

      Reference

        @@ -20257,40 +20257,40 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        Sometimes the thing you want to say is about the code, annotations provide a way to provide outside commentary on your code.

        @annotate: [left|right] [overrides] - [text]

        Annotate has a lot more controls than most of the other Twoslash commands, because each use of it probably needs to feel a bit different. Here's an example based on the TypeScript home page, click it to get it running so we can talk about what it does:

        -
        -
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        +
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        md
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +
        md
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +function compact(arr) {
        +    if (orr.length > 10) return arr.trim(0, 10)
        +    return arr
        +}
        +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        +```
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        +function compact(arr) { + if (orr.length > 10) return arr.trim(0, 10) + return arr +} +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr! +```

        First up, cool — it adds some text to the left hand side of the code. It features quite a few different options, so lets go through them one by one:

          @@ -20309,116 +20309,116 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        What's not included in this sample is flipped, which can be used to flip the arrow's orientation. Here's some examples:

        A horizontal right example:

        -
        -
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        +
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        md
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +
        md
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +function compact(arr) {
        +    if (orr.length > 10) return arr.trim(0, 10)
        +    return arr
        +}
        +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        +```
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        +function compact(arr) { + if (orr.length > 10) return arr.trim(0, 10) + return arr +} +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr! +```

        Upside down arrow pointing at the error, using flipped to re-flip the arrow:

        -
        -
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        +
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        md
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +
        md
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +function compact(arr) {
        +    if (orr.length > 10) return arr.trim(0, 10)
        +    return arr
        +}
        +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        +```
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        +function compact(arr) { + if (orr.length > 10) return arr.trim(0, 10) + return arr +} +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr! +```
        ]]> Queries

        Sometimes the thing you want to say is about the code, annotations provide a way to provide outside commentary on your code.

        @annotate: [left|right] [overrides] - [text]

        Annotate has a lot more controls than most of the other Twoslash commands, because each use of it probably needs to feel a bit different. Here's an example based on the TypeScript home page, click it to get it running so we can talk about what it does:

        -
        -
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        +
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        md
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +
        md
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +function compact(arr) {
        +    if (orr.length > 10) return arr.trim(0, 10)
        +    return arr
        +}
        +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        +```
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        +function compact(arr) { + if (orr.length > 10) return arr.trim(0, 10) + return arr +} +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr! +```

        First up, cool — it adds some text to the left hand side of the code. It features quite a few different options, so lets go through them one by one:

          @@ -20437,76 +20437,76 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        What's not included in this sample is flipped, which can be used to flip the arrow's orientation. Here's some examples:

        A horizontal right example:

        -
        -
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        +
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        md
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +
        md
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +function compact(arr) {
        +    if (orr.length > 10) return arr.trim(0, 10)
        +    return arr
        +}
        +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        +```
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        +function compact(arr) { + if (orr.length > 10) return arr.trim(0, 10) + return arr +} +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr! +```

        Upside down arrow pointing at the error, using flipped to re-flip the arrow:

        -
        -
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        +
        ts
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }
        +
        ts
        function compact(arr) {
        if (orr.length > 10) return arr.trim(0, 10)
        Cannot find name 'orr'.2304Cannot find name 'orr'.
        return arr
        }

        Discovered a typo, the param is arr, not orr!

        -
        md
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +
        md
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        ```ts twoslash
        -// @errors: 2304
        -// @strict: false
        +function compact(arr) {
        +    if (orr.length > 10) return arr.trim(0, 10)
        +    return arr
        +}
        +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        +```
        ```ts twoslash
        +// @errors: 2304
        +// @strict: false
         
        -function compact(arr) {
        -    if (orr.length > 10) return arr.trim(0, 10)
        -    return arr
        -}
        -// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
        -```
        +function compact(arr) { + if (orr.length > 10) return arr.trim(0, 10) + return arr +} +// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr! +```
        ]]>
        @@ -20519,126 +20519,126 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        Every Twoslash code example needs to be a complete TypeScript program so it can compile. Quite often to make it compile, there is a bunch of code which isn't relevant to the user. This can be extracted out of the code examples via cut comments.

        ---cut---

        Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the ---cut---.

        -
        -
        ts
        ts
        console.log(level)
        -
        ts
        console.log(level)
        -
        md
        ```ts twoslash
        -const level: string = 'Danger'
        -// ---cut---
        -console.log(level)
        -```
        ```ts twoslash
        -const level: string = 'Danger'
        -// ---cut---
        -console.log(level)
        -```
        +
        +
        ts
        ts
        console.log(level)
        +
        ts
        console.log(level)
        +
        md
        ```ts twoslash
        +const level: string = 'Danger'
        +// ---cut---
        +console.log(level)
        +```
        ```ts twoslash
        +const level: string = 'Danger'
        +// ---cut---
        +console.log(level)
        +```

        Cutting even works across multiple files. This is why // @filename: [file] is specifically the only Twoslash command which is not removed, because if it's not relevant it can be ---cut--- away.

        -
        -
        ts
        ts
        import { helloWorld } from './a'
        console.log(helloWorld)
        -
        ts
        import { helloWorld } from './a'
        console.log(helloWorld)
        -
        md
        ```ts twoslash
        -// @filename: a.ts
        -export const helloWorld: string = 'Hi'
        +
        +
        ts
        ts
        import { helloWorld } from './a'
        console.log(helloWorld)
        +
        ts
        import { helloWorld } from './a'
        console.log(helloWorld)
        +
        md
        ```ts twoslash
        +// @filename: a.ts
        +export const helloWorld: string = 'Hi'
         
        -// @filename: b.ts
        -// ---cut---
        -import { helloWorld } from './a'
        -console.log(helloWorld)
        -```
        ```ts twoslash
        -// @filename: a.ts
        -export const helloWorld: string = 'Hi'
        +// @filename: b.ts
        +// ---cut---
        +import { helloWorld } from './a'
        +console.log(helloWorld)
        +```
        ```ts twoslash
        +// @filename: a.ts
        +export const helloWorld: string = 'Hi'
         
        -// @filename: b.ts
        -// ---cut---
        -import { helloWorld } from './a'
        -console.log(helloWorld)
        -```
        +// @filename: b.ts +// ---cut--- +import { helloWorld } from './a' +console.log(helloWorld) +```

        ---cut-after---

        The sibling to ---cut---, which trims anything after the sigil:

        -
        -
        tsx
        tsx
        <Container>
        <ImportantComponent />
        </Container>
        -
        tsx
        <Container>
        <ImportantComponent />
        </Container>
        -
        md
        ```tsx twoslash
        -const Page = () => (
        -    // ---cut---
        -    <Container>
        -        <ImportantComponent />
        -    </Container>
        -    // ---cut-after---
        -)
        -```
        ```tsx twoslash
        -const Page = () => (
        -    // ---cut---
        -    <Container>
        -        <ImportantComponent />
        -    </Container>
        -    // ---cut-after---
        -)
        -```
        +
        +
        tsx
        tsx
        <Container>
        <ImportantComponent />
        </Container>
        +
        tsx
        <Container>
        <ImportantComponent />
        </Container>
        +
        md
        ```tsx twoslash
        +const Page = () => (
        +    // ---cut---
        +    <Container>
        +        <ImportantComponent />
        +    </Container>
        +    // ---cut-after---
        +)
        +```
        ```tsx twoslash
        +const Page = () => (
        +    // ---cut---
        +    <Container>
        +        <ImportantComponent />
        +    </Container>
        +    // ---cut-after---
        +)
        +```
        ]]> Cutting

        Every Twoslash code example needs to be a complete TypeScript program so it can compile. Quite often to make it compile, there is a bunch of code which isn't relevant to the user. This can be extracted out of the code examples via cut comments.

        ---cut---

        Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the ---cut---.

        -
        -
        ts
        ts
        console.log(level)
        -
        ts
        console.log(level)
        -
        md
        ```ts twoslash
        -const level: string = 'Danger'
        -// ---cut---
        -console.log(level)
        -```
        ```ts twoslash
        -const level: string = 'Danger'
        -// ---cut---
        -console.log(level)
        -```
        +
        +
        ts
        ts
        console.log(level)
        +
        ts
        console.log(level)
        +
        md
        ```ts twoslash
        +const level: string = 'Danger'
        +// ---cut---
        +console.log(level)
        +```
        ```ts twoslash
        +const level: string = 'Danger'
        +// ---cut---
        +console.log(level)
        +```

        Cutting even works across multiple files. This is why // @filename: [file] is specifically the only Twoslash command which is not removed, because if it's not relevant it can be ---cut--- away.

        -
        -
        ts
        ts
        import { helloWorld } from './a'
        console.log(helloWorld)
        -
        ts
        import { helloWorld } from './a'
        console.log(helloWorld)
        -
        md
        ```ts twoslash
        -// @filename: a.ts
        -export const helloWorld: string = 'Hi'
        +
        +
        ts
        ts
        import { helloWorld } from './a'
        console.log(helloWorld)
        +
        ts
        import { helloWorld } from './a'
        console.log(helloWorld)
        +
        md
        ```ts twoslash
        +// @filename: a.ts
        +export const helloWorld: string = 'Hi'
         
        -// @filename: b.ts
        -// ---cut---
        -import { helloWorld } from './a'
        -console.log(helloWorld)
        -```
        ```ts twoslash
        -// @filename: a.ts
        -export const helloWorld: string = 'Hi'
        +// @filename: b.ts
        +// ---cut---
        +import { helloWorld } from './a'
        +console.log(helloWorld)
        +```
        ```ts twoslash
        +// @filename: a.ts
        +export const helloWorld: string = 'Hi'
         
        -// @filename: b.ts
        -// ---cut---
        -import { helloWorld } from './a'
        -console.log(helloWorld)
        -```
        +// @filename: b.ts +// ---cut--- +import { helloWorld } from './a' +console.log(helloWorld) +```

        ---cut-after---

        The sibling to ---cut---, which trims anything after the sigil:

        -
        -
        tsx
        tsx
        <Container>
        <ImportantComponent />
        </Container>
        -
        tsx
        <Container>
        <ImportantComponent />
        </Container>
        -
        md
        ```tsx twoslash
        -const Page = () => (
        -    // ---cut---
        -    <Container>
        -        <ImportantComponent />
        -    </Container>
        -    // ---cut-after---
        -)
        -```
        ```tsx twoslash
        -const Page = () => (
        -    // ---cut---
        -    <Container>
        -        <ImportantComponent />
        -    </Container>
        -    // ---cut-after---
        -)
        -```
        +
        +
        tsx
        tsx
        <Container>
        <ImportantComponent />
        </Container>
        +
        tsx
        <Container>
        <ImportantComponent />
        </Container>
        +
        md
        ```tsx twoslash
        +const Page = () => (
        +    // ---cut---
        +    <Container>
        +        <ImportantComponent />
        +    </Container>
        +    // ---cut-after---
        +)
        +```
        ```tsx twoslash
        +const Page = () => (
        +    // ---cut---
        +    <Container>
        +        <ImportantComponent />
        +    </Container>
        +    // ---cut-after---
        +)
        +```
        ]]> @@ -20651,134 +20651,134 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        Running a Twoslash code example is a full TypeScript compiler run that will create files inside the virtual file system. You can replace the contents of your code examples with the results of running TypeScript over the project.

        @showEmit

        // @showEmit is the main command to tell Shiki Twoslash that you want to replace the output of your code example with the equivalent .js file.

        -
        -
        ts
        ts
        "use strict";
        const level = 'Danger';
         
        -
        ts
        "use strict";
        const level = 'Danger';
         
        -
        md
        ```ts twoslash
        -// @showEmit
        -const level: string = 'Danger'
        -```
        ```ts twoslash
        -// @showEmit
        -const level: string = 'Danger'
        -```
        +
        +
        ts
        ts
        "use strict";
        const level = 'Danger';
         
        +
        ts
        "use strict";
        const level = 'Danger';
         
        +
        md
        ```ts twoslash
        +// @showEmit
        +const level: string = 'Danger'
        +```
        ```ts twoslash
        +// @showEmit
        +const level: string = 'Danger'
        +```

        @showEmittedFile: [file]

        While the .js file is probably the most useful file out of the box, TypeScript does emit other files if you have the right flags enabled (.d.ts and .map) but also when you have a multi-file code sample — you might need to tell Twoslash which file to show. For all these cases you can also add @showEmittedFile: [file] to tell Twoslash which file you want to show.

        Shows emitted .d.ts for a TypeScript code example:

        -
        -
        md
        ```ts twoslash
        -// @declaration
        -// @showEmit
        -// @showEmittedFile: index.d.ts
        -export const hello = 'world'
        -```
        ```ts twoslash
        -// @declaration
        -// @showEmit
        -// @showEmittedFile: index.d.ts
        -export const hello = 'world'
        -```
        -
        ts
        ts
        export declare const hello = "world";
         
        -
        ts
        export declare const hello = "world";
         
        +
        +
        md
        ```ts twoslash
        +// @declaration
        +// @showEmit
        +// @showEmittedFile: index.d.ts
        +export const hello = 'world'
        +```
        ```ts twoslash
        +// @declaration
        +// @showEmit
        +// @showEmittedFile: index.d.ts
        +export const hello = 'world'
        +```
        +
        ts
        ts
        export declare const hello = "world";
         
        +
        ts
        export declare const hello = "world";
         

        Shows emitted .map files:

        -
        -
        md
        ```ts twoslash
        -// @sourceMap
        -// @showEmit
        -// @showEmittedFile: index.js.map
        -export const hello = 'world'
        -```
        ```ts twoslash
        -// @sourceMap
        -// @showEmit
        -// @showEmittedFile: index.js.map
        -export const hello = 'world'
        -```
        -
        ts
        ts
        {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
        -
        ts
        {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
        +
        +
        md
        ```ts twoslash
        +// @sourceMap
        +// @showEmit
        +// @showEmittedFile: index.js.map
        +export const hello = 'world'
        +```
        ```ts twoslash
        +// @sourceMap
        +// @showEmit
        +// @showEmittedFile: index.js.map
        +export const hello = 'world'
        +```
        +
        ts
        ts
        {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
        +
        ts
        {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
        -
        -
        md
        ```ts twoslash
        -// @declaration
        -// @declarationMap
        -// @showEmit
        -// @showEmittedFile: index.d.ts.map
        -export const hello = 'world'
        -```
        ```ts twoslash
        -// @declaration
        -// @declarationMap
        -// @showEmit
        -// @showEmittedFile: index.d.ts.map
        -export const hello = 'world'
        -```
        -
        ts
        ts
        {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
        -
        ts
        {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
        +
        +
        md
        ```ts twoslash
        +// @declaration
        +// @declarationMap
        +// @showEmit
        +// @showEmittedFile: index.d.ts.map
        +export const hello = 'world'
        +```
        ```ts twoslash
        +// @declaration
        +// @declarationMap
        +// @showEmit
        +// @showEmittedFile: index.d.ts.map
        +export const hello = 'world'
        +```
        +
        ts
        ts
        {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
        +
        ts
        {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
        ]]> Emit

        Running a Twoslash code example is a full TypeScript compiler run that will create files inside the virtual file system. You can replace the contents of your code examples with the results of running TypeScript over the project.

        @showEmit

        // @showEmit is the main command to tell Shiki Twoslash that you want to replace the output of your code example with the equivalent .js file.

        -
        -
        ts
        ts
        "use strict";
        const level = 'Danger';
         
        -
        ts
        "use strict";
        const level = 'Danger';
         
        -
        md
        ```ts twoslash
        -// @showEmit
        -const level: string = 'Danger'
        -```
        ```ts twoslash
        -// @showEmit
        -const level: string = 'Danger'
        -```
        +
        +
        ts
        ts
        "use strict";
        const level = 'Danger';
         
        +
        ts
        "use strict";
        const level = 'Danger';
         
        +
        md
        ```ts twoslash
        +// @showEmit
        +const level: string = 'Danger'
        +```
        ```ts twoslash
        +// @showEmit
        +const level: string = 'Danger'
        +```

        @showEmittedFile: [file]

        While the .js file is probably the most useful file out of the box, TypeScript does emit other files if you have the right flags enabled (.d.ts and .map) but also when you have a multi-file code sample — you might need to tell Twoslash which file to show. For all these cases you can also add @showEmittedFile: [file] to tell Twoslash which file you want to show.

        Shows emitted .d.ts for a TypeScript code example:

        -
        -
        md
        ```ts twoslash
        -// @declaration
        -// @showEmit
        -// @showEmittedFile: index.d.ts
        -export const hello = 'world'
        -```
        ```ts twoslash
        -// @declaration
        -// @showEmit
        -// @showEmittedFile: index.d.ts
        -export const hello = 'world'
        -```
        -
        ts
        ts
        export declare const hello = "world";
         
        -
        ts
        export declare const hello = "world";
         
        +
        +
        md
        ```ts twoslash
        +// @declaration
        +// @showEmit
        +// @showEmittedFile: index.d.ts
        +export const hello = 'world'
        +```
        ```ts twoslash
        +// @declaration
        +// @showEmit
        +// @showEmittedFile: index.d.ts
        +export const hello = 'world'
        +```
        +
        ts
        ts
        export declare const hello = "world";
         
        +
        ts
        export declare const hello = "world";
         

        Shows emitted .map files:

        -
        -
        md
        ```ts twoslash
        -// @sourceMap
        -// @showEmit
        -// @showEmittedFile: index.js.map
        -export const hello = 'world'
        -```
        ```ts twoslash
        -// @sourceMap
        -// @showEmit
        -// @showEmittedFile: index.js.map
        -export const hello = 'world'
        -```
        -
        ts
        ts
        {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
        -
        ts
        {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
        +
        +
        md
        ```ts twoslash
        +// @sourceMap
        +// @showEmit
        +// @showEmittedFile: index.js.map
        +export const hello = 'world'
        +```
        ```ts twoslash
        +// @sourceMap
        +// @showEmit
        +// @showEmittedFile: index.js.map
        +export const hello = 'world'
        +```
        +
        ts
        ts
        {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
        +
        ts
        {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA"}
        -
        -
        md
        ```ts twoslash
        -// @declaration
        -// @declarationMap
        -// @showEmit
        -// @showEmittedFile: index.d.ts.map
        -export const hello = 'world'
        -```
        ```ts twoslash
        -// @declaration
        -// @declarationMap
        -// @showEmit
        -// @showEmittedFile: index.d.ts.map
        -export const hello = 'world'
        -```
        -
        ts
        ts
        {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
        -
        ts
        {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
        +
        +
        md
        ```ts twoslash
        +// @declaration
        +// @declarationMap
        +// @showEmit
        +// @showEmittedFile: index.d.ts.map
        +export const hello = 'world'
        +```
        ```ts twoslash
        +// @declaration
        +// @declarationMap
        +// @showEmit
        +// @showEmittedFile: index.d.ts.map
        +export const hello = 'world'
        +```
        +
        ts
        ts
        {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
        +
        ts
        {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,UAAU,CAAA"}
        ]]> @@ -20793,33 +20793,33 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        @errors: [num]

        All TypeScript compiler errors have a number, this number is relatively arbitrary and can change between TypeScript versions. For our case these numbers are useul in declaring what we expect to see.

        You can use // @errors: [num] to tell Twoslash that you expect this error to occur. This moves the compiler error message into the code example.

        -
        -
        ts
        ts
        const a = '123'
        a = 132
        Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
        -
        ts
        const a = '123'
        a = 132
        Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
        -
        md
        ```ts twoslash
        -// @errors: 2588
        -const a = '123'
        -a = 132
        -```
        ```ts twoslash
        -// @errors: 2588
        -const a = '123'
        -a = 132
        -```
        +
        +
        ts
        ts
        const a = '123'
        a = 132
        Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
        +
        ts
        const a = '123'
        a = 132
        Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
        +
        md
        ```ts twoslash
        +// @errors: 2588
        +const a = '123'
        +a = 132
        +```
        ```ts twoslash
        +// @errors: 2588
        +const a = '123'
        +a = 132
        +```

        @noErrors

        Sometimes you have needs in which a broken TypeScript build is okay. A good example of this is using a completion query, which requires a broken TypeScript project to work. You can use // @noErrors to supress all errors in a code sample, and not have them show inline.

        -
        -
        ts
        ts
        const a = '123'
        a = 132
        -
        ts
        const a = '123'
        a = 132
        -
        md
        ```ts twoslash
        -// @noErrors
        -const a = '123'
        -a = 132
        -```
        ```ts twoslash
        -// @noErrors
        -const a = '123'
        -a = 132
        -```
        +
        +
        ts
        ts
        const a = '123'
        a = 132
        +
        ts
        const a = '123'
        a = 132
        +
        md
        ```ts twoslash
        +// @noErrors
        +const a = '123'
        +a = 132
        +```
        ```ts twoslash
        +// @noErrors
        +const a = '123'
        +a = 132
        +```
        ]]> Errors @@ -20828,33 +20828,33 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        @errors: [num]

        All TypeScript compiler errors have a number, this number is relatively arbitrary and can change between TypeScript versions. For our case these numbers are useul in declaring what we expect to see.

        You can use // @errors: [num] to tell Twoslash that you expect this error to occur. This moves the compiler error message into the code example.

        -
        -
        ts
        ts
        const a = '123'
        a = 132
        Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
        -
        ts
        const a = '123'
        a = 132
        Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
        -
        md
        ```ts twoslash
        -// @errors: 2588
        -const a = '123'
        -a = 132
        -```
        ```ts twoslash
        -// @errors: 2588
        -const a = '123'
        -a = 132
        -```
        +
        +
        ts
        ts
        const a = '123'
        a = 132
        Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
        +
        ts
        const a = '123'
        a = 132
        Cannot assign to 'a' because it is a constant.2588Cannot assign to 'a' because it is a constant.
        +
        md
        ```ts twoslash
        +// @errors: 2588
        +const a = '123'
        +a = 132
        +```
        ```ts twoslash
        +// @errors: 2588
        +const a = '123'
        +a = 132
        +```

        @noErrors

        Sometimes you have needs in which a broken TypeScript build is okay. A good example of this is using a completion query, which requires a broken TypeScript project to work. You can use // @noErrors to supress all errors in a code sample, and not have them show inline.

        -
        -
        ts
        ts
        const a = '123'
        a = 132
        -
        ts
        const a = '123'
        a = 132
        -
        md
        ```ts twoslash
        -// @noErrors
        -const a = '123'
        -a = 132
        -```
        ```ts twoslash
        -// @noErrors
        -const a = '123'
        -a = 132
        -```
        +
        +
        ts
        ts
        const a = '123'
        a = 132
        +
        ts
        const a = '123'
        a = 132
        +
        md
        ```ts twoslash
        +// @noErrors
        +const a = '123'
        +a = 132
        +```
        ```ts twoslash
        +// @noErrors
        +const a = '123'
        +a = 132
        +```
        ]]> @@ -20867,248 +20867,248 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        As your documentation grows, you may need a way of re-using code blocks to prevent code duplication. Shiki Twoslash provides a simple includes system.

        Defining a re-usable block

        Re-usable code blocks are defined by the twoslash language, followed by the include keyword and the reference name of your choice.

        -
        md
        ```twoslash include myBlock
        -type SomeString = string
        -```
        ```twoslash include myBlock
        -type SomeString = string
        -```
        +
        md
        ```twoslash include myBlock
        +type SomeString = string
        +```
        ```twoslash include myBlock
        +type SomeString = string
        +```

        Incremental steps

        Shiki Twoslash also provide the ability to define incremental steps through the definition of re-usable blocks. This means whenever a new step is delimited down the code, it will also include previous steps. These are not groups.

        • Incremental steps are delimited by // - [name of the step]
        • They are named at the end of the actual code
        -
        md
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +
        md
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```

        Including a whole block

        To include a re-usable block, add // @include: [block name] in your code block.

        twoslash
        -
        -
        ts
        ts
        type SomeString = string
        const a: SomeString = 'string'
        -
        ts
        type SomeString = string
        const a: SomeString = 'string'
        -
        md
        ```twoslash include myBlock
        -type SomeString = string
        -```
        +
        +
        ts
        ts
        type SomeString = string
        const a: SomeString = 'string'
        +
        ts
        type SomeString = string
        const a: SomeString = 'string'
        +
        md
        ```twoslash include myBlock
        +type SomeString = string
        +```
         
        -```ts twoslash
        -// @include: myBlock
        -const a: SomeString = 'string'
        -```
        ```twoslash include myBlock
        -type SomeString = string
        -```
        +```ts twoslash
        +// @include: myBlock
        +const a: SomeString = 'string'
        +```
        ```twoslash include myBlock
        +type SomeString = string
        +```
         
        -```ts twoslash
        -// @include: myBlock
        -const a: SomeString = 'string'
        -```
        +```ts twoslash +// @include: myBlock +const a: SomeString = 'string' +```

        Including a block step

        To include a re-usable block at a specific step, add // @include: [block name]-[step name] in your code block.

        twoslash
        -
        -
        ts
        ts
        type SomeString = string
        type SomeUser = { name: string; mail?: SomeUserMail }
        type SomeUserMail = { content: string; verified: boolean }
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        -
        ts
        type SomeString = string
        type SomeUser = { name: string; mail?: SomeUserMail }
        type SomeUserMail = { content: string; verified: boolean }
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        -
        md
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +
        +
        ts
        ts
        type SomeString = string
        type SomeUser = { name: string; mail?: SomeUserMail }
        type SomeUserMail = { content: string; verified: boolean }
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        +
        ts
        type SomeString = string
        type SomeUser = { name: string; mail?: SomeUserMail }
        type SomeUserMail = { content: string; verified: boolean }
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        +
        md
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
         
        -```ts twoslash
        -// @include: myBlockWithSteps-afterUserDefinitions
        -const mail: SomeUserMail = { content: 'some-email', verified: true }
        -```
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +```ts twoslash
        +// @include: myBlockWithSteps-afterUserDefinitions
        +const mail: SomeUserMail = { content: 'some-email', verified: true }
        +```
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
         
        -```ts twoslash
        -// @include: myBlockWithSteps-afterUserDefinitions
        -const mail: SomeUserMail = { content: 'some-email', verified: true }
        -```
        +```ts twoslash +// @include: myBlockWithSteps-afterUserDefinitions +const mail: SomeUserMail = { content: 'some-email', verified: true } +```

        Hiding re-used code

        Re-using a lot of TypeScript code can easily bloat your documentation and obstruct the main point of your code block. You can hide re-used code to keep your code blocks clean and concise by cutting right after the @include statement.

        -
        -
        ts
        ts
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        -
        ts
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        -
        md
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +
        +
        ts
        ts
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        +
        ts
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        +
        md
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
         
        -```ts twoslash
        -// @include: myBlockWithSteps-afterUserDefinitions
        -// ---cut---
        -const mail: SomeUserMail = { content: 'some-email', verified: true }
        -```
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +```ts twoslash
        +// @include: myBlockWithSteps-afterUserDefinitions
        +// ---cut---
        +const mail: SomeUserMail = { content: 'some-email', verified: true }
        +```
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
         
        -```ts twoslash
        -// @include: myBlockWithSteps-afterUserDefinitions
        -// ---cut---
        -const mail: SomeUserMail = { content: 'some-email', verified: true }
        -```
        +```ts twoslash +// @include: myBlockWithSteps-afterUserDefinitions +// ---cut--- +const mail: SomeUserMail = { content: 'some-email', verified: true } +```
        ]]> Includes

        As your documentation grows, you may need a way of re-using code blocks to prevent code duplication. Shiki Twoslash provides a simple includes system.

        Defining a re-usable block

        Re-usable code blocks are defined by the twoslash language, followed by the include keyword and the reference name of your choice.

        -
        md
        ```twoslash include myBlock
        -type SomeString = string
        -```
        ```twoslash include myBlock
        -type SomeString = string
        -```
        +
        md
        ```twoslash include myBlock
        +type SomeString = string
        +```
        ```twoslash include myBlock
        +type SomeString = string
        +```

        Incremental steps

        Shiki Twoslash also provide the ability to define incremental steps through the definition of re-usable blocks. This means whenever a new step is delimited down the code, it will also include previous steps. These are not groups.

        • Incremental steps are delimited by // - [name of the step]
        • They are named at the end of the actual code
        -
        md
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +
        md
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```

        Including a whole block

        To include a re-usable block, add // @include: [block name] in your code block.

        twoslash
        -
        -
        ts
        ts
        type SomeString = string
        const a: SomeString = 'string'
        -
        ts
        type SomeString = string
        const a: SomeString = 'string'
        -
        md
        ```twoslash include myBlock
        -type SomeString = string
        -```
        +
        +
        ts
        ts
        type SomeString = string
        const a: SomeString = 'string'
        +
        ts
        type SomeString = string
        const a: SomeString = 'string'
        +
        md
        ```twoslash include myBlock
        +type SomeString = string
        +```
         
        -```ts twoslash
        -// @include: myBlock
        -const a: SomeString = 'string'
        -```
        ```twoslash include myBlock
        -type SomeString = string
        -```
        +```ts twoslash
        +// @include: myBlock
        +const a: SomeString = 'string'
        +```
        ```twoslash include myBlock
        +type SomeString = string
        +```
         
        -```ts twoslash
        -// @include: myBlock
        -const a: SomeString = 'string'
        -```
        +```ts twoslash +// @include: myBlock +const a: SomeString = 'string' +```

        Including a block step

        To include a re-usable block at a specific step, add // @include: [block name]-[step name] in your code block.

        twoslash
        -
        -
        ts
        ts
        type SomeString = string
        type SomeUser = { name: string; mail?: SomeUserMail }
        type SomeUserMail = { content: string; verified: boolean }
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        -
        ts
        type SomeString = string
        type SomeUser = { name: string; mail?: SomeUserMail }
        type SomeUserMail = { content: string; verified: boolean }
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        -
        md
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +
        +
        ts
        ts
        type SomeString = string
        type SomeUser = { name: string; mail?: SomeUserMail }
        type SomeUserMail = { content: string; verified: boolean }
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        +
        ts
        type SomeString = string
        type SomeUser = { name: string; mail?: SomeUserMail }
        type SomeUserMail = { content: string; verified: boolean }
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        +
        md
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
         
        -```ts twoslash
        -// @include: myBlockWithSteps-afterUserDefinitions
        -const mail: SomeUserMail = { content: 'some-email', verified: true }
        -```
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +```ts twoslash
        +// @include: myBlockWithSteps-afterUserDefinitions
        +const mail: SomeUserMail = { content: 'some-email', verified: true }
        +```
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
         
        -```ts twoslash
        -// @include: myBlockWithSteps-afterUserDefinitions
        -const mail: SomeUserMail = { content: 'some-email', verified: true }
        -```
        +```ts twoslash +// @include: myBlockWithSteps-afterUserDefinitions +const mail: SomeUserMail = { content: 'some-email', verified: true } +```

        Hiding re-used code

        Re-using a lot of TypeScript code can easily bloat your documentation and obstruct the main point of your code block. You can hide re-used code to keep your code blocks clean and concise by cutting right after the @include statement.

        -
        -
        ts
        ts
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        -
        ts
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        -
        md
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +
        +
        ts
        ts
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        +
        ts
        const mail: SomeUserMail = { content: 'some-email', verified: true }
        +
        md
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
         
        -```ts twoslash
        -// @include: myBlockWithSteps-afterUserDefinitions
        -// ---cut---
        -const mail: SomeUserMail = { content: 'some-email', verified: true }
        -```
        ```twoslash include myBlockWithSteps
        -type SomeString = string
        -// - base
        -type SomeUser = { name: string; mail?: SomeUserMail }
        -type SomeUserMail = { content: string; verified: boolean }
        -// - afterUserDefinitions
        -type SomeGroup = { name: string; members: SomeUser[] }
        -// - afterGroupDefinitions
        -```
        +```ts twoslash
        +// @include: myBlockWithSteps-afterUserDefinitions
        +// ---cut---
        +const mail: SomeUserMail = { content: 'some-email', verified: true }
        +```
        ```twoslash include myBlockWithSteps
        +type SomeString = string
        +// - base
        +type SomeUser = { name: string; mail?: SomeUserMail }
        +type SomeUserMail = { content: string; verified: boolean }
        +// - afterUserDefinitions
        +type SomeGroup = { name: string; members: SomeUser[] }
        +// - afterGroupDefinitions
        +```
         
        -```ts twoslash
        -// @include: myBlockWithSteps-afterUserDefinitions
        -// ---cut---
        -const mail: SomeUserMail = { content: 'some-email', verified: true }
        -```
        +```ts twoslash +// @include: myBlockWithSteps-afterUserDefinitions +// ---cut--- +const mail: SomeUserMail = { content: 'some-email', verified: true } +```
        ]]> @@ -21122,28 +21122,28 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        This feature is effectively a facade, people will trust your output and it will look better.

        @log:, @warn:, @error:

        The names are based on the functions on the console object:

        -
        -
        ts
        ts
        console.log('Hello log')
        Hello log
         
        console.warn('Hello warn')
        Hello warn
         
        console.error('Hello error')
        Hello error
        -
        ts
        console.log('Hello log')
        Hello log
         
        console.warn('Hello warn')
        Hello warn
         
        console.error('Hello error')
        Hello error
        -
        md
        ```ts twoslash
        -console.log('Hello log')
        -// @log: Hello log
        +
        +
        ts
        ts
        console.log('Hello log')
        Hello log
         
        console.warn('Hello warn')
        Hello warn
         
        console.error('Hello error')
        Hello error
        +
        ts
        console.log('Hello log')
        Hello log
         
        console.warn('Hello warn')
        Hello warn
         
        console.error('Hello error')
        Hello error
        +
        md
        ```ts twoslash
        +console.log('Hello log')
        +// @log: Hello log
         
        -console.warn('Hello warn')
        -// @warn: Hello warn
        +console.warn('Hello warn')
        +// @warn: Hello warn
         
        -console.error('Hello error')
        -// @error: Hello error
        -```
        ```ts twoslash
        -console.log('Hello log')
        -// @log: Hello log
        +console.error('Hello error')
        +// @error: Hello error
        +```
        ```ts twoslash
        +console.log('Hello log')
        +// @log: Hello log
         
        -console.warn('Hello warn')
        -// @warn: Hello warn
        +console.warn('Hello warn')
        +// @warn: Hello warn
         
        -console.error('Hello error')
        -// @error: Hello error
        -```
        +console.error('Hello error') +// @error: Hello error +```
        ]]> Logging @@ -21151,28 +21151,28 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        This feature is effectively a facade, people will trust your output and it will look better.

        @log:, @warn:, @error:

        The names are based on the functions on the console object:

        -
        -
        ts
        ts
        console.log('Hello log')
        Hello log
         
        console.warn('Hello warn')
        Hello warn
         
        console.error('Hello error')
        Hello error
        -
        ts
        console.log('Hello log')
        Hello log
         
        console.warn('Hello warn')
        Hello warn
         
        console.error('Hello error')
        Hello error
        -
        md
        ```ts twoslash
        -console.log('Hello log')
        -// @log: Hello log
        +
        +
        ts
        ts
        console.log('Hello log')
        Hello log
         
        console.warn('Hello warn')
        Hello warn
         
        console.error('Hello error')
        Hello error
        +
        ts
        console.log('Hello log')
        Hello log
         
        console.warn('Hello warn')
        Hello warn
         
        console.error('Hello error')
        Hello error
        +
        md
        ```ts twoslash
        +console.log('Hello log')
        +// @log: Hello log
         
        -console.warn('Hello warn')
        -// @warn: Hello warn
        +console.warn('Hello warn')
        +// @warn: Hello warn
         
        -console.error('Hello error')
        -// @error: Hello error
        -```
        ```ts twoslash
        -console.log('Hello log')
        -// @log: Hello log
        +console.error('Hello error')
        +// @error: Hello error
        +```
        ```ts twoslash
        +console.log('Hello log')
        +// @log: Hello log
         
        -console.warn('Hello warn')
        -// @warn: Hello warn
        +console.warn('Hello warn')
        +// @warn: Hello warn
         
        -console.error('Hello error')
        -// @error: Hello error
        -```
        +console.error('Hello error') +// @error: Hello error +```
        ]]>
        @@ -21185,234 +21185,234 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        Twoslash code examples aren't limited to creating a single file, by using // @filename: [file] you can write any file to the virtual file system used by TypeScript to power your code examples.

        @filename: [file]

        Most of the time, you don't need to think about the underlaying virtual file system in a code example, but when you have imports between them it becomes important to know. Twoslash will default to creating an index.[type] based on the langauge passed to the code example:

        -
        -
        ts
        ts
        // I'm index.ts
        -
        ts
        // I'm index.ts
        -
        md
        ```ts twoslash
        -// I'm index.ts
        -```
        ```ts twoslash
        -// I'm index.ts
        -```
        +
        +
        ts
        ts
        // I'm index.ts
        +
        ts
        // I'm index.ts
        +
        md
        ```ts twoslash
        +// I'm index.ts
        +```
        ```ts twoslash
        +// I'm index.ts
        +```
        -
        -
        tsx
        tsx
        // I'm index.tsx
        -
        tsx
        // I'm index.tsx
        -
        md
        ```tsx twoslash
        -// I'm index.tsx
        -```
        ```tsx twoslash
        -// I'm index.tsx
        -```
        +
        +
        tsx
        tsx
        // I'm index.tsx
        +
        tsx
        // I'm index.tsx
        +
        md
        ```tsx twoslash
        +// I'm index.tsx
        +```
        ```tsx twoslash
        +// I'm index.tsx
        +```
        -
        -
        js
        js
        // I'm index.tjs
        -
        js
        // I'm index.tjs
        -
        md
        ```js twoslash
        -// I'm index.tjs
        -```
        ```js twoslash
        -// I'm index.tjs
        -```
        +
        +
        js
        js
        // I'm index.tjs
        +
        js
        // I'm index.tjs
        +
        md
        ```js twoslash
        +// I'm index.tjs
        +```
        ```js twoslash
        +// I'm index.tjs
        +```

        Then until Twoslash hits another // @filename: [file], the parser keeps adding new lines into the same file. After seeing @filename Twoslash creates a new virtual file-system file and adds the new lines to that. You can't edit a file after it was created, but you can overwrite it.

        It can be any file. For example, if you want to quickly fake a node module:

        -
        -
        ts
        ts
        // @filename: node_modules/@types/mylib/index.d.ts
        export function doit(): string
         
        // @filename: index.ts
        import { doit } from 'mylib'
        console.log(doit)
        -
        ts
        // @filename: node_modules/@types/mylib/index.d.ts
        export function doit(): string
         
        // @filename: index.ts
        import { doit } from 'mylib'
        console.log(doit)
        +
        +
        ts
        ts
        // @filename: node_modules/@types/mylib/index.d.ts
        export function doit(): string
         
        // @filename: index.ts
        import { doit } from 'mylib'
        console.log(doit)
        +
        ts
        // @filename: node_modules/@types/mylib/index.d.ts
        export function doit(): string
         
        // @filename: index.ts
        import { doit } from 'mylib'
        console.log(doit)

        This code example sets up the types for a non-existent npm module, and TypeScript picks it up as the definitions in the same way it would in a non-virtual TypeScript project.

        -
        md
        ```ts twoslash
        -// @filename: node_modules/@types/mylib/index.d.ts
        -export function doit(): string
        +
        md
        ```ts twoslash
        +// @filename: node_modules/@types/mylib/index.d.ts
        +export function doit(): string
         
        -// @filename: index.ts
        -import { doit } from 'mylib'
        -console.log(doit)
        -```
        ```ts twoslash
        -// @filename: node_modules/@types/mylib/index.d.ts
        -export function doit(): string
        +// @filename: index.ts
        +import { doit } from 'mylib'
        +console.log(doit)
        +```
        ```ts twoslash
        +// @filename: node_modules/@types/mylib/index.d.ts
        +export function doit(): string
         
        -// @filename: index.ts
        -import { doit } from 'mylib'
        -console.log(doit)
        -```
        +// @filename: index.ts +import { doit } from 'mylib' +console.log(doit) +```

        You can also set up a JSON object which can be imported in a TypeScript file:

        -
        -
        ts
        ts
        // @filename: app.json
        { "version": "23.2.3" }
         
        // @filename: index.ts
        import appSettings from "./app.json"
        appSettings.version
        (property) "version": string
        -
        ts
        // @filename: app.json
        { "version": "23.2.3" }
         
        // @filename: index.ts
        import appSettings from "./app.json"
        appSettings.version
        (property) "version": string
        -
        md
        ```ts twoslash
        -// @resolveJsonModule
        -// @filename: app.json
        -{ "version": "23.2.3" }
        +
        +
        ts
        ts
        // @filename: app.json
        { "version": "23.2.3" }
         
        // @filename: index.ts
        import appSettings from "./app.json"
        appSettings.version
        (property) "version": string
        +
        ts
        // @filename: app.json
        { "version": "23.2.3" }
         
        // @filename: index.ts
        import appSettings from "./app.json"
        appSettings.version
        (property) "version": string
        +
        md
        ```ts twoslash
        +// @resolveJsonModule
        +// @filename: app.json
        +{ "version": "23.2.3" }
         
        -// @filename: index.ts
        -import appSettings from "./app.json"
        -appSettings.version
        -//           ^?
        -```
        ```ts twoslash
        -// @resolveJsonModule
        -// @filename: app.json
        -{ "version": "23.2.3" }
        +// @filename: index.ts
        +import appSettings from "./app.json"
        +appSettings.version
        +//           ^?
        +```
        ```ts twoslash
        +// @resolveJsonModule
        +// @filename: app.json
        +{ "version": "23.2.3" }
         
        -// @filename: index.ts
        -import appSettings from "./app.json"
        -appSettings.version
        -//           ^?
        -```
        +// @filename: index.ts +import appSettings from "./app.json" +appSettings.version +// ^? +```

        Finally, the following code allows importing non-TypeScript content. There is a .d.ts file which globally says 'md files are OK to import' and 'the module "react" exists, but don't worry about the details'.

        Then for a user, they only see the imports and exports inside index.tsx.

        -
        -
        ts
        ts
        import React from "react"
        import MultiFileDocs from "./MultiFileDocs.mdx"
         
        export default () => <MultiFileDocs/>
        -
        ts
        import React from "react"
        import MultiFileDocs from "./MultiFileDocs.mdx"
         
        export default () => <MultiFileDocs/>
        -
        md
        ```ts twoslash
        -// @filename: ambient.d.ts
        -declare module '*.mdx' {
        -    export default any
        -}
        -declare module "react"
        +
        +
        ts
        ts
        import React from "react"
        import MultiFileDocs from "./MultiFileDocs.mdx"
         
        export default () => <MultiFileDocs/>
        +
        ts
        import React from "react"
        import MultiFileDocs from "./MultiFileDocs.mdx"
         
        export default () => <MultiFileDocs/>
        +
        md
        ```ts twoslash
        +// @filename: ambient.d.ts
        +declare module '*.mdx' {
        +    export default any
        +}
        +declare module "react"
         
        -// @filename: MultiFileDocs.mdx
        -## Hello world
        +// @filename: MultiFileDocs.mdx
        +## Hello world
         
        -// @filename: index.tsx
        -// ---cut---
        -import React from "react"
        -import MultiFileDocs from "./MultiFileDocs.mdx"
        +// @filename: index.tsx
        +// ---cut---
        +import React from "react"
        +import MultiFileDocs from "./MultiFileDocs.mdx"
         
        -export default () => <MultiFileDocs/>
        -```
        ```ts twoslash
        -// @filename: ambient.d.ts
        -declare module '*.mdx' {
        -    export default any
        -}
        -declare module "react"
        +export default () => <MultiFileDocs/>
        +```
        ```ts twoslash
        +// @filename: ambient.d.ts
        +declare module '*.mdx' {
        +    export default any
        +}
        +declare module "react"
         
        -// @filename: MultiFileDocs.mdx
        -## Hello world
        +// @filename: MultiFileDocs.mdx
        +## Hello world
         
        -// @filename: index.tsx
        -// ---cut---
        -import React from "react"
        -import MultiFileDocs from "./MultiFileDocs.mdx"
        +// @filename: index.tsx
        +// ---cut---
        +import React from "react"
        +import MultiFileDocs from "./MultiFileDocs.mdx"
         
        -export default () => <MultiFileDocs/>
        -```
        +export default () => <MultiFileDocs/> +```
        ]]> Multi-file

        Twoslash code examples aren't limited to creating a single file, by using // @filename: [file] you can write any file to the virtual file system used by TypeScript to power your code examples.

        @filename: [file]

        Most of the time, you don't need to think about the underlaying virtual file system in a code example, but when you have imports between them it becomes important to know. Twoslash will default to creating an index.[type] based on the langauge passed to the code example:

        -
        -
        ts
        ts
        // I'm index.ts
        -
        ts
        // I'm index.ts
        -
        md
        ```ts twoslash
        -// I'm index.ts
        -```
        ```ts twoslash
        -// I'm index.ts
        -```
        +
        +
        ts
        ts
        // I'm index.ts
        +
        ts
        // I'm index.ts
        +
        md
        ```ts twoslash
        +// I'm index.ts
        +```
        ```ts twoslash
        +// I'm index.ts
        +```
        -
        -
        tsx
        tsx
        // I'm index.tsx
        -
        tsx
        // I'm index.tsx
        -
        md
        ```tsx twoslash
        -// I'm index.tsx
        -```
        ```tsx twoslash
        -// I'm index.tsx
        -```
        +
        +
        tsx
        tsx
        // I'm index.tsx
        +
        tsx
        // I'm index.tsx
        +
        md
        ```tsx twoslash
        +// I'm index.tsx
        +```
        ```tsx twoslash
        +// I'm index.tsx
        +```
        -
        -
        js
        js
        // I'm index.tjs
        -
        js
        // I'm index.tjs
        -
        md
        ```js twoslash
        -// I'm index.tjs
        -```
        ```js twoslash
        -// I'm index.tjs
        -```
        +
        +
        js
        js
        // I'm index.tjs
        +
        js
        // I'm index.tjs
        +
        md
        ```js twoslash
        +// I'm index.tjs
        +```
        ```js twoslash
        +// I'm index.tjs
        +```

        Then until Twoslash hits another // @filename: [file], the parser keeps adding new lines into the same file. After seeing @filename Twoslash creates a new virtual file-system file and adds the new lines to that. You can't edit a file after it was created, but you can overwrite it.

        It can be any file. For example, if you want to quickly fake a node module:

        -
        -
        ts
        ts
        // @filename: node_modules/@types/mylib/index.d.ts
        export function doit(): string
         
        // @filename: index.ts
        import { doit } from 'mylib'
        console.log(doit)
        -
        ts
        // @filename: node_modules/@types/mylib/index.d.ts
        export function doit(): string
         
        // @filename: index.ts
        import { doit } from 'mylib'
        console.log(doit)
        +
        +
        ts
        ts
        // @filename: node_modules/@types/mylib/index.d.ts
        export function doit(): string
         
        // @filename: index.ts
        import { doit } from 'mylib'
        console.log(doit)
        +
        ts
        // @filename: node_modules/@types/mylib/index.d.ts
        export function doit(): string
         
        // @filename: index.ts
        import { doit } from 'mylib'
        console.log(doit)

        This code example sets up the types for a non-existent npm module, and TypeScript picks it up as the definitions in the same way it would in a non-virtual TypeScript project.

        -
        md
        ```ts twoslash
        -// @filename: node_modules/@types/mylib/index.d.ts
        -export function doit(): string
        +
        md
        ```ts twoslash
        +// @filename: node_modules/@types/mylib/index.d.ts
        +export function doit(): string
         
        -// @filename: index.ts
        -import { doit } from 'mylib'
        -console.log(doit)
        -```
        ```ts twoslash
        -// @filename: node_modules/@types/mylib/index.d.ts
        -export function doit(): string
        +// @filename: index.ts
        +import { doit } from 'mylib'
        +console.log(doit)
        +```
        ```ts twoslash
        +// @filename: node_modules/@types/mylib/index.d.ts
        +export function doit(): string
         
        -// @filename: index.ts
        -import { doit } from 'mylib'
        -console.log(doit)
        -```
        +// @filename: index.ts +import { doit } from 'mylib' +console.log(doit) +```

        You can also set up a JSON object which can be imported in a TypeScript file:

        -
        -
        ts
        ts
        // @filename: app.json
        { "version": "23.2.3" }
         
        // @filename: index.ts
        import appSettings from "./app.json"
        appSettings.version
        (property) "version": string
        -
        ts
        // @filename: app.json
        { "version": "23.2.3" }
         
        // @filename: index.ts
        import appSettings from "./app.json"
        appSettings.version
        (property) "version": string
        -
        md
        ```ts twoslash
        -// @resolveJsonModule
        -// @filename: app.json
        -{ "version": "23.2.3" }
        +
        +
        ts
        ts
        // @filename: app.json
        { "version": "23.2.3" }
         
        // @filename: index.ts
        import appSettings from "./app.json"
        appSettings.version
        (property) "version": string
        +
        ts
        // @filename: app.json
        { "version": "23.2.3" }
         
        // @filename: index.ts
        import appSettings from "./app.json"
        appSettings.version
        (property) "version": string
        +
        md
        ```ts twoslash
        +// @resolveJsonModule
        +// @filename: app.json
        +{ "version": "23.2.3" }
         
        -// @filename: index.ts
        -import appSettings from "./app.json"
        -appSettings.version
        -//           ^?
        -```
        ```ts twoslash
        -// @resolveJsonModule
        -// @filename: app.json
        -{ "version": "23.2.3" }
        +// @filename: index.ts
        +import appSettings from "./app.json"
        +appSettings.version
        +//           ^?
        +```
        ```ts twoslash
        +// @resolveJsonModule
        +// @filename: app.json
        +{ "version": "23.2.3" }
         
        -// @filename: index.ts
        -import appSettings from "./app.json"
        -appSettings.version
        -//           ^?
        -```
        +// @filename: index.ts +import appSettings from "./app.json" +appSettings.version +// ^? +```

        Finally, the following code allows importing non-TypeScript content. There is a .d.ts file which globally says 'md files are OK to import' and 'the module "react" exists, but don't worry about the details'.

        Then for a user, they only see the imports and exports inside index.tsx.

        -
        -
        ts
        ts
        import React from "react"
        import MultiFileDocs from "./MultiFileDocs.mdx"
         
        export default () => <MultiFileDocs/>
        -
        ts
        import React from "react"
        import MultiFileDocs from "./MultiFileDocs.mdx"
         
        export default () => <MultiFileDocs/>
        -
        md
        ```ts twoslash
        -// @filename: ambient.d.ts
        -declare module '*.mdx' {
        -    export default any
        -}
        -declare module "react"
        +
        +
        ts
        ts
        import React from "react"
        import MultiFileDocs from "./MultiFileDocs.mdx"
         
        export default () => <MultiFileDocs/>
        +
        ts
        import React from "react"
        import MultiFileDocs from "./MultiFileDocs.mdx"
         
        export default () => <MultiFileDocs/>
        +
        md
        ```ts twoslash
        +// @filename: ambient.d.ts
        +declare module '*.mdx' {
        +    export default any
        +}
        +declare module "react"
         
        -// @filename: MultiFileDocs.mdx
        -## Hello world
        +// @filename: MultiFileDocs.mdx
        +## Hello world
         
        -// @filename: index.tsx
        -// ---cut---
        -import React from "react"
        -import MultiFileDocs from "./MultiFileDocs.mdx"
        +// @filename: index.tsx
        +// ---cut---
        +import React from "react"
        +import MultiFileDocs from "./MultiFileDocs.mdx"
         
        -export default () => <MultiFileDocs/>
        -```
        ```ts twoslash
        -// @filename: ambient.d.ts
        -declare module '*.mdx' {
        -    export default any
        -}
        -declare module "react"
        +export default () => <MultiFileDocs/>
        +```
        ```ts twoslash
        +// @filename: ambient.d.ts
        +declare module '*.mdx' {
        +    export default any
        +}
        +declare module "react"
         
        -// @filename: MultiFileDocs.mdx
        -## Hello world
        +// @filename: MultiFileDocs.mdx
        +## Hello world
         
        -// @filename: index.tsx
        -// ---cut---
        -import React from "react"
        -import MultiFileDocs from "./MultiFileDocs.mdx"
        +// @filename: index.tsx
        +// ---cut---
        +import React from "react"
        +import MultiFileDocs from "./MultiFileDocs.mdx"
         
        -export default () => <MultiFileDocs/>
        -```
        +export default () => <MultiFileDocs/> +```
        ]]> @@ -21425,33 +21425,33 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code. Twoslash comes with two different ways to query your code: ?^ and ?|.

        Extract Type ^?

        Using ^? you can pull out type information about a particular identifier in the line of code above it.

        -
        -
        ts
        ts
        const hi = 'Hello'
        const msg = hi + ', world'
        const msg: string
        -
        ts
        const hi = 'Hello'
        const msg = hi + ', world'
        const msg: string
        -
        md
        ```ts twoslash
        -const hi = 'Hello'
        -const msg = hi + ', world'
        -//    ^?
        -```
        ```ts twoslash
        -const hi = 'Hello'
        -const msg = hi + ', world'
        -//    ^?
        -```
        +
        +
        ts
        ts
        const hi = 'Hello'
        const msg = hi + ', world'
        const msg: string
        +
        ts
        const hi = 'Hello'
        const msg = hi + ', world'
        const msg: string
        +
        md
        ```ts twoslash
        +const hi = 'Hello'
        +const msg = hi + ', world'
        +//    ^?
        +```
        ```ts twoslash
        +const hi = 'Hello'
        +const msg = hi + ', world'
        +//    ^?
        +```

        Completions ^|

        Using ^| you can pull out information about a what the auto-complete looks like at a particular location.

        -
        -
        ts
        ts
        console.e
                 
        -
        ts
        console.e
                 
        -
        md
        ```ts twoslash
        -// @noErrors
        -console.e
        -//       ^|
        -```
        ```ts twoslash
        -// @noErrors
        -console.e
        -//       ^|
        -```
        +
        +
        ts
        ts
        console.e
                 
        +
        ts
        console.e
                 
        +
        md
        ```ts twoslash
        +// @noErrors
        +console.e
        +//       ^|
        +```
        ```ts twoslash
        +// @noErrors
        +console.e
        +//       ^|
        +```

        INFO

        Note that the compiler flag for // @noErrors is set, because console.e is a failing TypeScript code sample but we don't really care about that.

        @@ -21461,33 +21461,33 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code. Twoslash comes with two different ways to query your code: ?^ and ?|.

        Extract Type ^?

        Using ^? you can pull out type information about a particular identifier in the line of code above it.

        -
        -
        ts
        ts
        const hi = 'Hello'
        const msg = hi + ', world'
        const msg: string
        -
        ts
        const hi = 'Hello'
        const msg = hi + ', world'
        const msg: string
        -
        md
        ```ts twoslash
        -const hi = 'Hello'
        -const msg = hi + ', world'
        -//    ^?
        -```
        ```ts twoslash
        -const hi = 'Hello'
        -const msg = hi + ', world'
        -//    ^?
        -```
        +
        +
        ts
        ts
        const hi = 'Hello'
        const msg = hi + ', world'
        const msg: string
        +
        ts
        const hi = 'Hello'
        const msg = hi + ', world'
        const msg: string
        +
        md
        ```ts twoslash
        +const hi = 'Hello'
        +const msg = hi + ', world'
        +//    ^?
        +```
        ```ts twoslash
        +const hi = 'Hello'
        +const msg = hi + ', world'
        +//    ^?
        +```

        Completions ^|

        Using ^| you can pull out information about a what the auto-complete looks like at a particular location.

        -
        -
        ts
        ts
        console.e
                 
        -
        ts
        console.e
                 
        -
        md
        ```ts twoslash
        -// @noErrors
        -console.e
        -//       ^|
        -```
        ```ts twoslash
        -// @noErrors
        -console.e
        -//       ^|
        -```
        +
        +
        ts
        ts
        console.e
                 
        +
        ts
        console.e
                 
        +
        md
        ```ts twoslash
        +// @noErrors
        +console.e
        +//       ^|
        +```
        ```ts twoslash
        +// @noErrors
        +console.e
        +//       ^|
        +```

        INFO

        Note that the compiler flag for // @noErrors is set, because console.e is a failing TypeScript code sample but we don't really care about that.

        @@ -21504,60 +21504,60 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        Twoslash works by faking a virtual file system over your existing file system. This means any @types or libraries with TypeScript definitions should work out of the box with no config.

        Local Sources

        Simply import locally installed libraries and Twoslash can pick up types:

        -
        -
        ts
        ts
        import { defineConfig } from 'vitepress'
        const config = defineConfig({})
        const config: UserConfig<DefaultTheme.Config>
        export default config
        -
        ts
        import { defineConfig } from 'vitepress'
        const config = defineConfig({})
        const config: UserConfig<DefaultTheme.Config>
        export default config
        -
        md
        ```ts twoslash
        -import { defineConfig } from 'vitepress'
        -const config = defineConfig({})
        -//    ^?
        -export default config
        -```
        ```ts twoslash
        -import { defineConfig } from 'vitepress'
        -const config = defineConfig({})
        -//    ^?
        -export default config
        -```
        +
        +
        ts
        ts
        import { defineConfig } from 'vitepress'
        const config = defineConfig({})
        const config: UserConfig<DefaultTheme.Config>
        export default config
        +
        ts
        import { defineConfig } from 'vitepress'
        const config = defineConfig({})
        const config: UserConfig<DefaultTheme.Config>
        export default config
        +
        md
        ```ts twoslash
        +import { defineConfig } from 'vitepress'
        +const config = defineConfig({})
        +//    ^?
        +export default config
        +```
        ```ts twoslash
        +import { defineConfig } from 'vitepress'
        +const config = defineConfig({})
        +//    ^?
        +export default config
        +```

        Globals

        Setting up globals is a little bit more complex, but not drastically. You need to use the triple slash reference which adds a particular library to the global scope.

        For example, setting up Node imports and globals etc.

        -
        -
        ts
        ts
        import { writeFileSync } from 'fs'
        writeFileSync('myfile.txt', '// TODO')
        -
        ts
        import { writeFileSync } from 'fs'
        writeFileSync('myfile.txt', '// TODO')
        -
        md
        ```ts twoslash
        -/// <reference types="node" />
        -// ---cut---
        -import { writeFileSync } from 'fs'
        -writeFileSync('myfile.txt', '// TODO')
        -```
        ```ts twoslash
        -/// <reference types="node" />
        -// ---cut---
        -import { writeFileSync } from 'fs'
        -writeFileSync('myfile.txt', '// TODO')
        -```
        +
        +
        ts
        ts
        import { writeFileSync } from 'fs'
        writeFileSync('myfile.txt', '// TODO')
        +
        ts
        import { writeFileSync } from 'fs'
        writeFileSync('myfile.txt', '// TODO')
        +
        md
        ```ts twoslash
        +/// <reference types="node" />
        +// ---cut---
        +import { writeFileSync } from 'fs'
        +writeFileSync('myfile.txt', '// TODO')
        +```
        ```ts twoslash
        +/// <reference types="node" />
        +// ---cut---
        +import { writeFileSync } from 'fs'
        +writeFileSync('myfile.txt', '// TODO')
        +```

        APIs like Vitest are similar cases where you would use a triple slash reference.

        -
        -
        ts
        ts
        test('my tests', () => {
        expect('hello').toEqual('hello')
        const expect: ExpectStatic
        })
        -
        ts
        test('my tests', () => {
        expect('hello').toEqual('hello')
        const expect: ExpectStatic
        })
        -
        md
        ```ts twoslash
        -/// <reference types="vitest/globals" />
        -// ---cut---
        +
        +
        ts
        ts
        test('my tests', () => {
        expect('hello').toEqual('hello')
        const expect: ExpectStatic
        })
        +
        ts
        test('my tests', () => {
        expect('hello').toEqual('hello')
        const expect: ExpectStatic
        })
        +
        md
        ```ts twoslash
        +/// <reference types="vitest/globals" />
        +// ---cut---
         
        -test('my tests', () => {
        -    expect('hello').toEqual('hello')
        -    // ^?
        -})
        -```
        ```ts twoslash
        -/// <reference types="vitest/globals" />
        -// ---cut---
        +test('my tests', () => {
        +    expect('hello').toEqual('hello')
        +    // ^?
        +})
        +```
        ```ts twoslash
        +/// <reference types="vitest/globals" />
        +// ---cut---
         
        -test('my tests', () => {
        -    expect('hello').toEqual('hello')
        -    // ^?
        -})
        -```
        +test('my tests', () => { + expect('hello').toEqual('hello') + // ^? +}) +```
        ]]> @types @@ -21565,60 +21565,60 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

        Twoslash works by faking a virtual file system over your existing file system. This means any @types or libraries with TypeScript definitions should work out of the box with no config.

        Local Sources

        Simply import locally installed libraries and Twoslash can pick up types:

        -
        -
        ts
        ts
        import { defineConfig } from 'vitepress'
        const config = defineConfig({})
        const config: UserConfig<DefaultTheme.Config>
        export default config
        -
        ts
        import { defineConfig } from 'vitepress'
        const config = defineConfig({})
        const config: UserConfig<DefaultTheme.Config>
        export default config
        -
        md
        ```ts twoslash
        -import { defineConfig } from 'vitepress'
        -const config = defineConfig({})
        -//    ^?
        -export default config
        -```
        ```ts twoslash
        -import { defineConfig } from 'vitepress'
        -const config = defineConfig({})
        -//    ^?
        -export default config
        -```
        +
        +
        ts
        ts
        import { defineConfig } from 'vitepress'
        const config = defineConfig({})
        const config: UserConfig<DefaultTheme.Config>
        export default config
        +
        ts
        import { defineConfig } from 'vitepress'
        const config = defineConfig({})
        const config: UserConfig<DefaultTheme.Config>
        export default config
        +
        md
        ```ts twoslash
        +import { defineConfig } from 'vitepress'
        +const config = defineConfig({})
        +//    ^?
        +export default config
        +```
        ```ts twoslash
        +import { defineConfig } from 'vitepress'
        +const config = defineConfig({})
        +//    ^?
        +export default config
        +```

        Globals

        Setting up globals is a little bit more complex, but not drastically. You need to use the triple slash reference which adds a particular library to the global scope.

        For example, setting up Node imports and globals etc.

        -
        -
        ts
        ts
        import { writeFileSync } from 'fs'
        writeFileSync('myfile.txt', '// TODO')
        -
        ts
        import { writeFileSync } from 'fs'
        writeFileSync('myfile.txt', '// TODO')
        -
        md
        ```ts twoslash
        -/// <reference types="node" />
        -// ---cut---
        -import { writeFileSync } from 'fs'
        -writeFileSync('myfile.txt', '// TODO')
        -```
        ```ts twoslash
        -/// <reference types="node" />
        -// ---cut---
        -import { writeFileSync } from 'fs'
        -writeFileSync('myfile.txt', '// TODO')
        -```
        +
        +
        ts
        ts
        import { writeFileSync } from 'fs'
        writeFileSync('myfile.txt', '// TODO')
        +
        ts
        import { writeFileSync } from 'fs'
        writeFileSync('myfile.txt', '// TODO')
        +
        md
        ```ts twoslash
        +/// <reference types="node" />
        +// ---cut---
        +import { writeFileSync } from 'fs'
        +writeFileSync('myfile.txt', '// TODO')
        +```
        ```ts twoslash
        +/// <reference types="node" />
        +// ---cut---
        +import { writeFileSync } from 'fs'
        +writeFileSync('myfile.txt', '// TODO')
        +```

        APIs like Vitest are similar cases where you would use a triple slash reference.

        -
        -
        ts
        ts
        test('my tests', () => {
        expect('hello').toEqual('hello')
        const expect: ExpectStatic
        })
        -
        ts
        test('my tests', () => {
        expect('hello').toEqual('hello')
        const expect: ExpectStatic
        })
        -
        md
        ```ts twoslash
        -/// <reference types="vitest/globals" />
        -// ---cut---
        +
        +
        ts
        ts
        test('my tests', () => {
        expect('hello').toEqual('hello')
        const expect: ExpectStatic
        })
        +
        ts
        test('my tests', () => {
        expect('hello').toEqual('hello')
        const expect: ExpectStatic
        })
        +
        md
        ```ts twoslash
        +/// <reference types="vitest/globals" />
        +// ---cut---
         
        -test('my tests', () => {
        -    expect('hello').toEqual('hello')
        -    // ^?
        -})
        -```
        ```ts twoslash
        -/// <reference types="vitest/globals" />
        -// ---cut---
        +test('my tests', () => {
        +    expect('hello').toEqual('hello')
        +    // ^?
        +})
        +```
        ```ts twoslash
        +/// <reference types="vitest/globals" />
        +// ---cut---
         
        -test('my tests', () => {
        -    expect('hello').toEqual('hello')
        -    // ^?
        -})
        -```
        +test('my tests', () => { + expect('hello').toEqual('hello') + // ^? +}) +```
        ]]> @@ -21628,1190 +21628,1190 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3 https://note.toshiki.devapplication/vitepress-plugin-shiki-twoslash/config/flags Thu, 01 Jul 2021 00:00:00 GMT Compiler Flags -
        // @allowJs
        -Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
        -
        -// @allowSyntheticDefaultImports
        -Allow 'import x from y' when a module doesn't have a default export..
        -
        -// @allowUmdGlobalAccess
        -Allow accessing UMD globals from modules..
        -
        -// @allowUnreachableCode
        -Disable error reporting for unreachable code..
        -
        -// @allowUnusedLabels
        -Disable error reporting for unused labels..
        -
        -// @alwaysStrict
        -Ensure 'use strict' is always emitted..
        -
        -// @assumeChangesOnlyAffectDirectDependencies
        -Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
        -
        -// @baseUrl
        -Specify the base directory to resolve non-relative module names..
        -
        -// @charset
        -No longer supported. In early versions, manually set the text encoding for reading files..
        -
        -// @checkJs
        -Enable error reporting in type-checked JavaScript files..
        -
        -// @composite
        -Enable constraints that allow a TypeScript project to be used with project references..
        -
        -// @declaration
        -Generate .d.ts files from TypeScript and JavaScript files in your project..
        -
        -// @declarationDir
        -Specify the output directory for generated declaration files..
        -
        -// @declarationMap
        -Create sourcemaps for d.ts files..
        -
        -// @diagnostics
        -Output compiler performance information after building..
        -
        -// @disableReferencedProjectLoad
        -Reduce the number of projects loaded automatically by TypeScript..
        -
        -// @disableSizeLimit
        -Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
        -
        -// @disableSolutionSearching
        -Opt a project out of multi-project reference checking when editing..
        -
        -// @disableSourceOfProjectReferenceRedirect
        -Disable preferring source files instead of declaration files when referencing composite projects.
        -
        -// @downlevelIteration
        -Emit more compliant, but verbose and less performant JavaScript for iteration..
        -
        -// @emitBOM
        -Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
        -
        -// @emitDeclarationOnly
        -Only output d.ts files and not JavaScript files..
        -
        -// @emitDecoratorMetadata
        -Emit design-type metadata for decorated declarations in source files..
        -
        -// @esModuleInterop
        -Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
        -
        -// @exactOptionalPropertyTypes
        -Interpret optional property types as written, rather than adding 'undefined'..
        -
        -// @experimentalDecorators
        -Enable experimental support for TC39 stage 2 draft decorators..
        -
        -// @explainFiles
        -Print files read during the compilation including why it was included..
        -
        -// @extendedDiagnostics
        -Output more detailed compiler performance information after building..
        -
        -// @forceConsistentCasingInFileNames
        -Ensure that casing is correct in imports..
        -
        -// @generateCpuProfile
        -Emit a v8 CPU profile of the compiler run for debugging..
        -
        -// @importHelpers
        -Allow importing helper functions from tslib once per project, instead of including them per-file..
        -
        -// @importsNotUsedAsValues
        -Specify emit/checking behavior for imports that are only used for types.
        -
        -// @incremental
        -Enable incremental compilation.
        -
        -// @inlineSourceMap
        -Include sourcemap files inside the emitted JavaScript..
        -
        -// @inlineSources
        -Include source code in the sourcemaps inside the emitted JavaScript..
        -
        -// @isolatedModules
        -Ensure that each file can be safely transpiled without relying on other imports..
        -
        -// @jsx
        -Specify what JSX code is generated..
        -
        -// @jsxFactory
        -Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
        -
        -// @jsxFragmentFactory
        -Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
        -
        -// @jsxImportSource
        -Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
        -
        -// @keyofStringsOnly
        -Make keyof only return strings instead of string, numbers or symbols. Legacy option..
        -
        -// @lib
        -Specify a set of bundled library declaration files that describe the target runtime environment..
        -
        -// @listEmittedFiles
        -Print the names of emitted files after a compilation..
        -
        -// @listFiles
        -Print all of the files read during the compilation..
        -
        -// @mapRoot
        -Specify the location where debugger should locate map files instead of generated locations..
        -
        -// @maxNodeModuleJsDepth
        -Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
        -
        -// @module
        -Specify what module code is generated..
        -
        -// @moduleResolution
        -Specify how TypeScript looks up a file from a given module specifier..
        -
        -// @newLine
        -Set the newline character for emitting files..
        -
        -// @noEmit
        -Disable emitting file from a compilation..
        -
        -// @noEmitHelpers
        -Disable generating custom helper functions like `__extends` in compiled output..
        -
        -// @noEmitOnError
        -Disable emitting files if any type checking errors are reported..
        -
        -// @noErrorTruncation
        -Disable truncating types in error messages..
        -
        -// @noFallthroughCasesInSwitch
        -Enable error reporting for fallthrough cases in switch statements..
        -
        -// @noImplicitAny
        -Enable error reporting for expressions and declarations with an implied `any` type...
        -
        -// @noImplicitOverride
        -Add `undefined` to a type when accessed using an index..
        -
        -// @noImplicitReturns
        -Enable error reporting for codepaths that do not explicitly return in a function..
        -
        -// @noImplicitThis
        -Enable error reporting when `this` is given the type `any`..
        -
        -// @noImplicitUseStrict
        -Disable adding 'use strict' directives in emitted JavaScript files..
        -
        -// @noLib
        -Disable including any library files, including the default lib.d.ts..
        -
        -// @noPropertyAccessFromIndexSignature
        -Enforces using indexed accessors for keys declared using an indexed type.
        -
        -// @noResolve
        -Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
        -
        -// @noStrictGenericChecks
        -Disable strict checking of generic signatures in function types..
        -
        -// @noUncheckedIndexedAccess
        -Include 'undefined' in index signature results.
        -
        -// @noUnusedLocals
        -Enable error reporting when a local variables aren't read..
        -
        -// @noUnusedParameters
        -Raise an error when a function parameter isn't read.
        -
        -// @out
        -Deprecated setting. Use `outFile` instead..
        -
        -// @outDir
        -Specify an output folder for all emitted files..
        -
        -// @outFile
        -Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
        -
        -// @paths
        -Specify a set of entries that re-map imports to additional lookup locations..
        -
        -// @plugins
        -List of language service plugins..
        -
        -// @preserveConstEnums
        -Disable erasing `const enum` declarations in generated code..
        -
        -// @preserveSymlinks
        -Disable resolving symlinks to their realpath. This correlates to the same flag in node..
        -
        -// @preserveWatchOutput
        -Disable wiping the console in watch mode.
        -
        -// @pretty
        -Enable color and formatting in output to make compiler errors easier to read.
        -
        -// @reactNamespace
        -Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
        -
        -// @removeComments
        -Disable emitting comments..
        -
        -// @resolveJsonModule
        -Enable importing .json files.
        -
        -// @rootDir
        -Specify the root folder within your source files..
        -
        -// @rootDirs
        -Allow multiple folders to be treated as one when resolving modules..
        -
        -// @skipDefaultLibCheck
        -Skip type checking .d.ts files that are included with TypeScript..
        -
        -// @skipLibCheck
        -Skip type checking all .d.ts files..
        -
        -// @sourceMap
        -Create source map files for emitted JavaScript files..
        -
        -// @sourceRoot
        -Specify the root path for debuggers to find the reference source code..
        -
        -// @strict
        -Enable all strict type-checking options..
        -
        -// @strictBindCallApply
        -Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
        -
        -// @strictFunctionTypes
        -When assigning functions, check to ensure parameters and the return values are subtype-compatible..
        -
        -// @strictNullChecks
        -When type checking, take into account `null` and `undefined`..
        -
        -// @strictPropertyInitialization
        -Check for class properties that are declared but not set in the constructor..
        -
        -// @stripInternal
        -Disable emitting declarations that have `@internal` in their JSDoc comments..
        -
        -// @suppressExcessPropertyErrors
        -Disable reporting of excess property errors during the creation of object literals..
        -
        -// @suppressImplicitAnyIndexErrors
        -Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
        -
        -// @target
        -Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
        -
        -// @traceResolution
        -Log paths used during the `moduleResolution` process..
        -
        -// @tsBuildInfoFile
        -Specify the folder for .tsbuildinfo incremental compilation files..
        -
        -// @typeRoots
        -Specify multiple folders that act like `./node_modules/@types`..
        -
        -// @types
        -Specify type package names to be included without being referenced in a source file..
        -
        -// @useDefineForClassFields
        -Emit ECMAScript-standard-compliant class fields..
        -
        -// @useUnknownInCatchVariables
        -Type catch clause variables as 'unknown' instead of 'any'..
        // @allowJs
        -Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
        -
        -// @allowSyntheticDefaultImports
        -Allow 'import x from y' when a module doesn't have a default export..
        -
        -// @allowUmdGlobalAccess
        -Allow accessing UMD globals from modules..
        -
        -// @allowUnreachableCode
        -Disable error reporting for unreachable code..
        -
        -// @allowUnusedLabels
        -Disable error reporting for unused labels..
        -
        -// @alwaysStrict
        -Ensure 'use strict' is always emitted..
        -
        -// @assumeChangesOnlyAffectDirectDependencies
        -Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
        -
        -// @baseUrl
        -Specify the base directory to resolve non-relative module names..
        -
        -// @charset
        -No longer supported. In early versions, manually set the text encoding for reading files..
        -
        -// @checkJs
        -Enable error reporting in type-checked JavaScript files..
        -
        -// @composite
        -Enable constraints that allow a TypeScript project to be used with project references..
        -
        -// @declaration
        -Generate .d.ts files from TypeScript and JavaScript files in your project..
        -
        -// @declarationDir
        -Specify the output directory for generated declaration files..
        -
        -// @declarationMap
        -Create sourcemaps for d.ts files..
        -
        -// @diagnostics
        -Output compiler performance information after building..
        -
        -// @disableReferencedProjectLoad
        -Reduce the number of projects loaded automatically by TypeScript..
        -
        -// @disableSizeLimit
        -Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
        -
        -// @disableSolutionSearching
        -Opt a project out of multi-project reference checking when editing..
        -
        -// @disableSourceOfProjectReferenceRedirect
        -Disable preferring source files instead of declaration files when referencing composite projects.
        -
        -// @downlevelIteration
        -Emit more compliant, but verbose and less performant JavaScript for iteration..
        -
        -// @emitBOM
        -Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
        -
        -// @emitDeclarationOnly
        -Only output d.ts files and not JavaScript files..
        -
        -// @emitDecoratorMetadata
        -Emit design-type metadata for decorated declarations in source files..
        -
        -// @esModuleInterop
        -Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
        -
        -// @exactOptionalPropertyTypes
        -Interpret optional property types as written, rather than adding 'undefined'..
        -
        -// @experimentalDecorators
        -Enable experimental support for TC39 stage 2 draft decorators..
        -
        -// @explainFiles
        -Print files read during the compilation including why it was included..
        -
        -// @extendedDiagnostics
        -Output more detailed compiler performance information after building..
        -
        -// @forceConsistentCasingInFileNames
        -Ensure that casing is correct in imports..
        -
        -// @generateCpuProfile
        -Emit a v8 CPU profile of the compiler run for debugging..
        -
        -// @importHelpers
        -Allow importing helper functions from tslib once per project, instead of including them per-file..
        -
        -// @importsNotUsedAsValues
        -Specify emit/checking behavior for imports that are only used for types.
        -
        -// @incremental
        -Enable incremental compilation.
        -
        -// @inlineSourceMap
        -Include sourcemap files inside the emitted JavaScript..
        -
        -// @inlineSources
        -Include source code in the sourcemaps inside the emitted JavaScript..
        -
        -// @isolatedModules
        -Ensure that each file can be safely transpiled without relying on other imports..
        -
        -// @jsx
        -Specify what JSX code is generated..
        -
        -// @jsxFactory
        -Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
        -
        -// @jsxFragmentFactory
        -Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
        -
        -// @jsxImportSource
        -Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
        -
        -// @keyofStringsOnly
        -Make keyof only return strings instead of string, numbers or symbols. Legacy option..
        -
        -// @lib
        -Specify a set of bundled library declaration files that describe the target runtime environment..
        -
        -// @listEmittedFiles
        -Print the names of emitted files after a compilation..
        -
        -// @listFiles
        -Print all of the files read during the compilation..
        -
        -// @mapRoot
        -Specify the location where debugger should locate map files instead of generated locations..
        -
        -// @maxNodeModuleJsDepth
        -Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
        -
        -// @module
        -Specify what module code is generated..
        -
        -// @moduleResolution
        -Specify how TypeScript looks up a file from a given module specifier..
        -
        -// @newLine
        -Set the newline character for emitting files..
        -
        -// @noEmit
        -Disable emitting file from a compilation..
        -
        -// @noEmitHelpers
        -Disable generating custom helper functions like `__extends` in compiled output..
        -
        -// @noEmitOnError
        -Disable emitting files if any type checking errors are reported..
        -
        -// @noErrorTruncation
        -Disable truncating types in error messages..
        -
        -// @noFallthroughCasesInSwitch
        -Enable error reporting for fallthrough cases in switch statements..
        -
        -// @noImplicitAny
        -Enable error reporting for expressions and declarations with an implied `any` type...
        -
        -// @noImplicitOverride
        -Add `undefined` to a type when accessed using an index..
        -
        -// @noImplicitReturns
        -Enable error reporting for codepaths that do not explicitly return in a function..
        -
        -// @noImplicitThis
        -Enable error reporting when `this` is given the type `any`..
        -
        -// @noImplicitUseStrict
        -Disable adding 'use strict' directives in emitted JavaScript files..
        -
        -// @noLib
        -Disable including any library files, including the default lib.d.ts..
        -
        -// @noPropertyAccessFromIndexSignature
        -Enforces using indexed accessors for keys declared using an indexed type.
        -
        -// @noResolve
        -Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
        -
        -// @noStrictGenericChecks
        -Disable strict checking of generic signatures in function types..
        -
        -// @noUncheckedIndexedAccess
        -Include 'undefined' in index signature results.
        -
        -// @noUnusedLocals
        -Enable error reporting when a local variables aren't read..
        -
        -// @noUnusedParameters
        -Raise an error when a function parameter isn't read.
        -
        -// @out
        -Deprecated setting. Use `outFile` instead..
        -
        -// @outDir
        -Specify an output folder for all emitted files..
        -
        -// @outFile
        -Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
        -
        -// @paths
        -Specify a set of entries that re-map imports to additional lookup locations..
        -
        -// @plugins
        -List of language service plugins..
        -
        -// @preserveConstEnums
        -Disable erasing `const enum` declarations in generated code..
        -
        -// @preserveSymlinks
        -Disable resolving symlinks to their realpath. This correlates to the same flag in node..
        -
        -// @preserveWatchOutput
        -Disable wiping the console in watch mode.
        -
        -// @pretty
        -Enable color and formatting in output to make compiler errors easier to read.
        -
        -// @reactNamespace
        -Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
        -
        -// @removeComments
        -Disable emitting comments..
        -
        -// @resolveJsonModule
        -Enable importing .json files.
        -
        -// @rootDir
        -Specify the root folder within your source files..
        -
        -// @rootDirs
        -Allow multiple folders to be treated as one when resolving modules..
        -
        -// @skipDefaultLibCheck
        -Skip type checking .d.ts files that are included with TypeScript..
        -
        -// @skipLibCheck
        -Skip type checking all .d.ts files..
        -
        -// @sourceMap
        -Create source map files for emitted JavaScript files..
        -
        -// @sourceRoot
        -Specify the root path for debuggers to find the reference source code..
        -
        -// @strict
        -Enable all strict type-checking options..
        -
        -// @strictBindCallApply
        -Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
        -
        -// @strictFunctionTypes
        -When assigning functions, check to ensure parameters and the return values are subtype-compatible..
        -
        -// @strictNullChecks
        -When type checking, take into account `null` and `undefined`..
        -
        -// @strictPropertyInitialization
        -Check for class properties that are declared but not set in the constructor..
        -
        -// @stripInternal
        -Disable emitting declarations that have `@internal` in their JSDoc comments..
        -
        -// @suppressExcessPropertyErrors
        -Disable reporting of excess property errors during the creation of object literals..
        -
        -// @suppressImplicitAnyIndexErrors
        -Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
        -
        -// @target
        -Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
        -
        -// @traceResolution
        -Log paths used during the `moduleResolution` process..
        -
        -// @tsBuildInfoFile
        -Specify the folder for .tsbuildinfo incremental compilation files..
        -
        -// @typeRoots
        -Specify multiple folders that act like `./node_modules/@types`..
        -
        -// @types
        -Specify type package names to be included without being referenced in a source file..
        -
        -// @useDefineForClassFields
        -Emit ECMAScript-standard-compliant class fields..
        -
        -// @useUnknownInCatchVariables
        -Type catch clause variables as 'unknown' instead of 'any'..
        +
        // @allowJs
        +Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
        +
        +// @allowSyntheticDefaultImports
        +Allow 'import x from y' when a module doesn't have a default export..
        +
        +// @allowUmdGlobalAccess
        +Allow accessing UMD globals from modules..
        +
        +// @allowUnreachableCode
        +Disable error reporting for unreachable code..
        +
        +// @allowUnusedLabels
        +Disable error reporting for unused labels..
        +
        +// @alwaysStrict
        +Ensure 'use strict' is always emitted..
        +
        +// @assumeChangesOnlyAffectDirectDependencies
        +Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
        +
        +// @baseUrl
        +Specify the base directory to resolve non-relative module names..
        +
        +// @charset
        +No longer supported. In early versions, manually set the text encoding for reading files..
        +
        +// @checkJs
        +Enable error reporting in type-checked JavaScript files..
        +
        +// @composite
        +Enable constraints that allow a TypeScript project to be used with project references..
        +
        +// @declaration
        +Generate .d.ts files from TypeScript and JavaScript files in your project..
        +
        +// @declarationDir
        +Specify the output directory for generated declaration files..
        +
        +// @declarationMap
        +Create sourcemaps for d.ts files..
        +
        +// @diagnostics
        +Output compiler performance information after building..
        +
        +// @disableReferencedProjectLoad
        +Reduce the number of projects loaded automatically by TypeScript..
        +
        +// @disableSizeLimit
        +Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
        +
        +// @disableSolutionSearching
        +Opt a project out of multi-project reference checking when editing..
        +
        +// @disableSourceOfProjectReferenceRedirect
        +Disable preferring source files instead of declaration files when referencing composite projects.
        +
        +// @downlevelIteration
        +Emit more compliant, but verbose and less performant JavaScript for iteration..
        +
        +// @emitBOM
        +Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
        +
        +// @emitDeclarationOnly
        +Only output d.ts files and not JavaScript files..
        +
        +// @emitDecoratorMetadata
        +Emit design-type metadata for decorated declarations in source files..
        +
        +// @esModuleInterop
        +Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
        +
        +// @exactOptionalPropertyTypes
        +Interpret optional property types as written, rather than adding 'undefined'..
        +
        +// @experimentalDecorators
        +Enable experimental support for TC39 stage 2 draft decorators..
        +
        +// @explainFiles
        +Print files read during the compilation including why it was included..
        +
        +// @extendedDiagnostics
        +Output more detailed compiler performance information after building..
        +
        +// @forceConsistentCasingInFileNames
        +Ensure that casing is correct in imports..
        +
        +// @generateCpuProfile
        +Emit a v8 CPU profile of the compiler run for debugging..
        +
        +// @importHelpers
        +Allow importing helper functions from tslib once per project, instead of including them per-file..
        +
        +// @importsNotUsedAsValues
        +Specify emit/checking behavior for imports that are only used for types.
        +
        +// @incremental
        +Enable incremental compilation.
        +
        +// @inlineSourceMap
        +Include sourcemap files inside the emitted JavaScript..
        +
        +// @inlineSources
        +Include source code in the sourcemaps inside the emitted JavaScript..
        +
        +// @isolatedModules
        +Ensure that each file can be safely transpiled without relying on other imports..
        +
        +// @jsx
        +Specify what JSX code is generated..
        +
        +// @jsxFactory
        +Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
        +
        +// @jsxFragmentFactory
        +Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
        +
        +// @jsxImportSource
        +Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
        +
        +// @keyofStringsOnly
        +Make keyof only return strings instead of string, numbers or symbols. Legacy option..
        +
        +// @lib
        +Specify a set of bundled library declaration files that describe the target runtime environment..
        +
        +// @listEmittedFiles
        +Print the names of emitted files after a compilation..
        +
        +// @listFiles
        +Print all of the files read during the compilation..
        +
        +// @mapRoot
        +Specify the location where debugger should locate map files instead of generated locations..
        +
        +// @maxNodeModuleJsDepth
        +Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
        +
        +// @module
        +Specify what module code is generated..
        +
        +// @moduleResolution
        +Specify how TypeScript looks up a file from a given module specifier..
        +
        +// @newLine
        +Set the newline character for emitting files..
        +
        +// @noEmit
        +Disable emitting file from a compilation..
        +
        +// @noEmitHelpers
        +Disable generating custom helper functions like `__extends` in compiled output..
        +
        +// @noEmitOnError
        +Disable emitting files if any type checking errors are reported..
        +
        +// @noErrorTruncation
        +Disable truncating types in error messages..
        +
        +// @noFallthroughCasesInSwitch
        +Enable error reporting for fallthrough cases in switch statements..
        +
        +// @noImplicitAny
        +Enable error reporting for expressions and declarations with an implied `any` type...
        +
        +// @noImplicitOverride
        +Add `undefined` to a type when accessed using an index..
        +
        +// @noImplicitReturns
        +Enable error reporting for codepaths that do not explicitly return in a function..
        +
        +// @noImplicitThis
        +Enable error reporting when `this` is given the type `any`..
        +
        +// @noImplicitUseStrict
        +Disable adding 'use strict' directives in emitted JavaScript files..
        +
        +// @noLib
        +Disable including any library files, including the default lib.d.ts..
        +
        +// @noPropertyAccessFromIndexSignature
        +Enforces using indexed accessors for keys declared using an indexed type.
        +
        +// @noResolve
        +Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
        +
        +// @noStrictGenericChecks
        +Disable strict checking of generic signatures in function types..
        +
        +// @noUncheckedIndexedAccess
        +Include 'undefined' in index signature results.
        +
        +// @noUnusedLocals
        +Enable error reporting when a local variables aren't read..
        +
        +// @noUnusedParameters
        +Raise an error when a function parameter isn't read.
        +
        +// @out
        +Deprecated setting. Use `outFile` instead..
        +
        +// @outDir
        +Specify an output folder for all emitted files..
        +
        +// @outFile
        +Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
        +
        +// @paths
        +Specify a set of entries that re-map imports to additional lookup locations..
        +
        +// @plugins
        +List of language service plugins..
        +
        +// @preserveConstEnums
        +Disable erasing `const enum` declarations in generated code..
        +
        +// @preserveSymlinks
        +Disable resolving symlinks to their realpath. This correlates to the same flag in node..
        +
        +// @preserveWatchOutput
        +Disable wiping the console in watch mode.
        +
        +// @pretty
        +Enable color and formatting in output to make compiler errors easier to read.
        +
        +// @reactNamespace
        +Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
        +
        +// @removeComments
        +Disable emitting comments..
        +
        +// @resolveJsonModule
        +Enable importing .json files.
        +
        +// @rootDir
        +Specify the root folder within your source files..
        +
        +// @rootDirs
        +Allow multiple folders to be treated as one when resolving modules..
        +
        +// @skipDefaultLibCheck
        +Skip type checking .d.ts files that are included with TypeScript..
        +
        +// @skipLibCheck
        +Skip type checking all .d.ts files..
        +
        +// @sourceMap
        +Create source map files for emitted JavaScript files..
        +
        +// @sourceRoot
        +Specify the root path for debuggers to find the reference source code..
        +
        +// @strict
        +Enable all strict type-checking options..
        +
        +// @strictBindCallApply
        +Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
        +
        +// @strictFunctionTypes
        +When assigning functions, check to ensure parameters and the return values are subtype-compatible..
        +
        +// @strictNullChecks
        +When type checking, take into account `null` and `undefined`..
        +
        +// @strictPropertyInitialization
        +Check for class properties that are declared but not set in the constructor..
        +
        +// @stripInternal
        +Disable emitting declarations that have `@internal` in their JSDoc comments..
        +
        +// @suppressExcessPropertyErrors
        +Disable reporting of excess property errors during the creation of object literals..
        +
        +// @suppressImplicitAnyIndexErrors
        +Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
        +
        +// @target
        +Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
        +
        +// @traceResolution
        +Log paths used during the `moduleResolution` process..
        +
        +// @tsBuildInfoFile
        +Specify the folder for .tsbuildinfo incremental compilation files..
        +
        +// @typeRoots
        +Specify multiple folders that act like `./node_modules/@types`..
        +
        +// @types
        +Specify type package names to be included without being referenced in a source file..
        +
        +// @useDefineForClassFields
        +Emit ECMAScript-standard-compliant class fields..
        +
        +// @useUnknownInCatchVariables
        +Type catch clause variables as 'unknown' instead of 'any'..
        // @allowJs
        +Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
        +
        +// @allowSyntheticDefaultImports
        +Allow 'import x from y' when a module doesn't have a default export..
        +
        +// @allowUmdGlobalAccess
        +Allow accessing UMD globals from modules..
        +
        +// @allowUnreachableCode
        +Disable error reporting for unreachable code..
        +
        +// @allowUnusedLabels
        +Disable error reporting for unused labels..
        +
        +// @alwaysStrict
        +Ensure 'use strict' is always emitted..
        +
        +// @assumeChangesOnlyAffectDirectDependencies
        +Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
        +
        +// @baseUrl
        +Specify the base directory to resolve non-relative module names..
        +
        +// @charset
        +No longer supported. In early versions, manually set the text encoding for reading files..
        +
        +// @checkJs
        +Enable error reporting in type-checked JavaScript files..
        +
        +// @composite
        +Enable constraints that allow a TypeScript project to be used with project references..
        +
        +// @declaration
        +Generate .d.ts files from TypeScript and JavaScript files in your project..
        +
        +// @declarationDir
        +Specify the output directory for generated declaration files..
        +
        +// @declarationMap
        +Create sourcemaps for d.ts files..
        +
        +// @diagnostics
        +Output compiler performance information after building..
        +
        +// @disableReferencedProjectLoad
        +Reduce the number of projects loaded automatically by TypeScript..
        +
        +// @disableSizeLimit
        +Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
        +
        +// @disableSolutionSearching
        +Opt a project out of multi-project reference checking when editing..
        +
        +// @disableSourceOfProjectReferenceRedirect
        +Disable preferring source files instead of declaration files when referencing composite projects.
        +
        +// @downlevelIteration
        +Emit more compliant, but verbose and less performant JavaScript for iteration..
        +
        +// @emitBOM
        +Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
        +
        +// @emitDeclarationOnly
        +Only output d.ts files and not JavaScript files..
        +
        +// @emitDecoratorMetadata
        +Emit design-type metadata for decorated declarations in source files..
        +
        +// @esModuleInterop
        +Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
        +
        +// @exactOptionalPropertyTypes
        +Interpret optional property types as written, rather than adding 'undefined'..
        +
        +// @experimentalDecorators
        +Enable experimental support for TC39 stage 2 draft decorators..
        +
        +// @explainFiles
        +Print files read during the compilation including why it was included..
        +
        +// @extendedDiagnostics
        +Output more detailed compiler performance information after building..
        +
        +// @forceConsistentCasingInFileNames
        +Ensure that casing is correct in imports..
        +
        +// @generateCpuProfile
        +Emit a v8 CPU profile of the compiler run for debugging..
        +
        +// @importHelpers
        +Allow importing helper functions from tslib once per project, instead of including them per-file..
        +
        +// @importsNotUsedAsValues
        +Specify emit/checking behavior for imports that are only used for types.
        +
        +// @incremental
        +Enable incremental compilation.
        +
        +// @inlineSourceMap
        +Include sourcemap files inside the emitted JavaScript..
        +
        +// @inlineSources
        +Include source code in the sourcemaps inside the emitted JavaScript..
        +
        +// @isolatedModules
        +Ensure that each file can be safely transpiled without relying on other imports..
        +
        +// @jsx
        +Specify what JSX code is generated..
        +
        +// @jsxFactory
        +Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
        +
        +// @jsxFragmentFactory
        +Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
        +
        +// @jsxImportSource
        +Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
        +
        +// @keyofStringsOnly
        +Make keyof only return strings instead of string, numbers or symbols. Legacy option..
        +
        +// @lib
        +Specify a set of bundled library declaration files that describe the target runtime environment..
        +
        +// @listEmittedFiles
        +Print the names of emitted files after a compilation..
        +
        +// @listFiles
        +Print all of the files read during the compilation..
        +
        +// @mapRoot
        +Specify the location where debugger should locate map files instead of generated locations..
        +
        +// @maxNodeModuleJsDepth
        +Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
        +
        +// @module
        +Specify what module code is generated..
        +
        +// @moduleResolution
        +Specify how TypeScript looks up a file from a given module specifier..
        +
        +// @newLine
        +Set the newline character for emitting files..
        +
        +// @noEmit
        +Disable emitting file from a compilation..
        +
        +// @noEmitHelpers
        +Disable generating custom helper functions like `__extends` in compiled output..
        +
        +// @noEmitOnError
        +Disable emitting files if any type checking errors are reported..
        +
        +// @noErrorTruncation
        +Disable truncating types in error messages..
        +
        +// @noFallthroughCasesInSwitch
        +Enable error reporting for fallthrough cases in switch statements..
        +
        +// @noImplicitAny
        +Enable error reporting for expressions and declarations with an implied `any` type...
        +
        +// @noImplicitOverride
        +Add `undefined` to a type when accessed using an index..
        +
        +// @noImplicitReturns
        +Enable error reporting for codepaths that do not explicitly return in a function..
        +
        +// @noImplicitThis
        +Enable error reporting when `this` is given the type `any`..
        +
        +// @noImplicitUseStrict
        +Disable adding 'use strict' directives in emitted JavaScript files..
        +
        +// @noLib
        +Disable including any library files, including the default lib.d.ts..
        +
        +// @noPropertyAccessFromIndexSignature
        +Enforces using indexed accessors for keys declared using an indexed type.
        +
        +// @noResolve
        +Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
        +
        +// @noStrictGenericChecks
        +Disable strict checking of generic signatures in function types..
        +
        +// @noUncheckedIndexedAccess
        +Include 'undefined' in index signature results.
        +
        +// @noUnusedLocals
        +Enable error reporting when a local variables aren't read..
        +
        +// @noUnusedParameters
        +Raise an error when a function parameter isn't read.
        +
        +// @out
        +Deprecated setting. Use `outFile` instead..
        +
        +// @outDir
        +Specify an output folder for all emitted files..
        +
        +// @outFile
        +Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
        +
        +// @paths
        +Specify a set of entries that re-map imports to additional lookup locations..
        +
        +// @plugins
        +List of language service plugins..
        +
        +// @preserveConstEnums
        +Disable erasing `const enum` declarations in generated code..
        +
        +// @preserveSymlinks
        +Disable resolving symlinks to their realpath. This correlates to the same flag in node..
        +
        +// @preserveWatchOutput
        +Disable wiping the console in watch mode.
        +
        +// @pretty
        +Enable color and formatting in output to make compiler errors easier to read.
        +
        +// @reactNamespace
        +Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
        +
        +// @removeComments
        +Disable emitting comments..
        +
        +// @resolveJsonModule
        +Enable importing .json files.
        +
        +// @rootDir
        +Specify the root folder within your source files..
        +
        +// @rootDirs
        +Allow multiple folders to be treated as one when resolving modules..
        +
        +// @skipDefaultLibCheck
        +Skip type checking .d.ts files that are included with TypeScript..
        +
        +// @skipLibCheck
        +Skip type checking all .d.ts files..
        +
        +// @sourceMap
        +Create source map files for emitted JavaScript files..
        +
        +// @sourceRoot
        +Specify the root path for debuggers to find the reference source code..
        +
        +// @strict
        +Enable all strict type-checking options..
        +
        +// @strictBindCallApply
        +Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
        +
        +// @strictFunctionTypes
        +When assigning functions, check to ensure parameters and the return values are subtype-compatible..
        +
        +// @strictNullChecks
        +When type checking, take into account `null` and `undefined`..
        +
        +// @strictPropertyInitialization
        +Check for class properties that are declared but not set in the constructor..
        +
        +// @stripInternal
        +Disable emitting declarations that have `@internal` in their JSDoc comments..
        +
        +// @suppressExcessPropertyErrors
        +Disable reporting of excess property errors during the creation of object literals..
        +
        +// @suppressImplicitAnyIndexErrors
        +Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
        +
        +// @target
        +Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
        +
        +// @traceResolution
        +Log paths used during the `moduleResolution` process..
        +
        +// @tsBuildInfoFile
        +Specify the folder for .tsbuildinfo incremental compilation files..
        +
        +// @typeRoots
        +Specify multiple folders that act like `./node_modules/@types`..
        +
        +// @types
        +Specify type package names to be included without being referenced in a source file..
        +
        +// @useDefineForClassFields
        +Emit ECMAScript-standard-compliant class fields..
        +
        +// @useUnknownInCatchVariables
        +Type catch clause variables as 'unknown' instead of 'any'..
        ]]> Compiler Flags -
        // @allowJs
        -Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
        -
        -// @allowSyntheticDefaultImports
        -Allow 'import x from y' when a module doesn't have a default export..
        -
        -// @allowUmdGlobalAccess
        -Allow accessing UMD globals from modules..
        -
        -// @allowUnreachableCode
        -Disable error reporting for unreachable code..
        -
        -// @allowUnusedLabels
        -Disable error reporting for unused labels..
        -
        -// @alwaysStrict
        -Ensure 'use strict' is always emitted..
        -
        -// @assumeChangesOnlyAffectDirectDependencies
        -Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
        -
        -// @baseUrl
        -Specify the base directory to resolve non-relative module names..
        -
        -// @charset
        -No longer supported. In early versions, manually set the text encoding for reading files..
        -
        -// @checkJs
        -Enable error reporting in type-checked JavaScript files..
        -
        -// @composite
        -Enable constraints that allow a TypeScript project to be used with project references..
        -
        -// @declaration
        -Generate .d.ts files from TypeScript and JavaScript files in your project..
        -
        -// @declarationDir
        -Specify the output directory for generated declaration files..
        -
        -// @declarationMap
        -Create sourcemaps for d.ts files..
        -
        -// @diagnostics
        -Output compiler performance information after building..
        -
        -// @disableReferencedProjectLoad
        -Reduce the number of projects loaded automatically by TypeScript..
        -
        -// @disableSizeLimit
        -Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
        -
        -// @disableSolutionSearching
        -Opt a project out of multi-project reference checking when editing..
        -
        -// @disableSourceOfProjectReferenceRedirect
        -Disable preferring source files instead of declaration files when referencing composite projects.
        -
        -// @downlevelIteration
        -Emit more compliant, but verbose and less performant JavaScript for iteration..
        -
        -// @emitBOM
        -Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
        -
        -// @emitDeclarationOnly
        -Only output d.ts files and not JavaScript files..
        -
        -// @emitDecoratorMetadata
        -Emit design-type metadata for decorated declarations in source files..
        -
        -// @esModuleInterop
        -Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
        -
        -// @exactOptionalPropertyTypes
        -Interpret optional property types as written, rather than adding 'undefined'..
        -
        -// @experimentalDecorators
        -Enable experimental support for TC39 stage 2 draft decorators..
        -
        -// @explainFiles
        -Print files read during the compilation including why it was included..
        -
        -// @extendedDiagnostics
        -Output more detailed compiler performance information after building..
        -
        -// @forceConsistentCasingInFileNames
        -Ensure that casing is correct in imports..
        -
        -// @generateCpuProfile
        -Emit a v8 CPU profile of the compiler run for debugging..
        -
        -// @importHelpers
        -Allow importing helper functions from tslib once per project, instead of including them per-file..
        -
        -// @importsNotUsedAsValues
        -Specify emit/checking behavior for imports that are only used for types.
        -
        -// @incremental
        -Enable incremental compilation.
        -
        -// @inlineSourceMap
        -Include sourcemap files inside the emitted JavaScript..
        -
        -// @inlineSources
        -Include source code in the sourcemaps inside the emitted JavaScript..
        -
        -// @isolatedModules
        -Ensure that each file can be safely transpiled without relying on other imports..
        -
        -// @jsx
        -Specify what JSX code is generated..
        -
        -// @jsxFactory
        -Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
        -
        -// @jsxFragmentFactory
        -Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
        -
        -// @jsxImportSource
        -Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
        -
        -// @keyofStringsOnly
        -Make keyof only return strings instead of string, numbers or symbols. Legacy option..
        -
        -// @lib
        -Specify a set of bundled library declaration files that describe the target runtime environment..
        -
        -// @listEmittedFiles
        -Print the names of emitted files after a compilation..
        -
        -// @listFiles
        -Print all of the files read during the compilation..
        -
        -// @mapRoot
        -Specify the location where debugger should locate map files instead of generated locations..
        -
        -// @maxNodeModuleJsDepth
        -Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
        -
        -// @module
        -Specify what module code is generated..
        -
        -// @moduleResolution
        -Specify how TypeScript looks up a file from a given module specifier..
        -
        -// @newLine
        -Set the newline character for emitting files..
        -
        -// @noEmit
        -Disable emitting file from a compilation..
        -
        -// @noEmitHelpers
        -Disable generating custom helper functions like `__extends` in compiled output..
        -
        -// @noEmitOnError
        -Disable emitting files if any type checking errors are reported..
        -
        -// @noErrorTruncation
        -Disable truncating types in error messages..
        -
        -// @noFallthroughCasesInSwitch
        -Enable error reporting for fallthrough cases in switch statements..
        -
        -// @noImplicitAny
        -Enable error reporting for expressions and declarations with an implied `any` type...
        -
        -// @noImplicitOverride
        -Add `undefined` to a type when accessed using an index..
        -
        -// @noImplicitReturns
        -Enable error reporting for codepaths that do not explicitly return in a function..
        -
        -// @noImplicitThis
        -Enable error reporting when `this` is given the type `any`..
        -
        -// @noImplicitUseStrict
        -Disable adding 'use strict' directives in emitted JavaScript files..
        -
        -// @noLib
        -Disable including any library files, including the default lib.d.ts..
        -
        -// @noPropertyAccessFromIndexSignature
        -Enforces using indexed accessors for keys declared using an indexed type.
        -
        -// @noResolve
        -Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
        -
        -// @noStrictGenericChecks
        -Disable strict checking of generic signatures in function types..
        -
        -// @noUncheckedIndexedAccess
        -Include 'undefined' in index signature results.
        -
        -// @noUnusedLocals
        -Enable error reporting when a local variables aren't read..
        -
        -// @noUnusedParameters
        -Raise an error when a function parameter isn't read.
        -
        -// @out
        -Deprecated setting. Use `outFile` instead..
        -
        -// @outDir
        -Specify an output folder for all emitted files..
        -
        -// @outFile
        -Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
        -
        -// @paths
        -Specify a set of entries that re-map imports to additional lookup locations..
        -
        -// @plugins
        -List of language service plugins..
        -
        -// @preserveConstEnums
        -Disable erasing `const enum` declarations in generated code..
        -
        -// @preserveSymlinks
        -Disable resolving symlinks to their realpath. This correlates to the same flag in node..
        -
        -// @preserveWatchOutput
        -Disable wiping the console in watch mode.
        -
        -// @pretty
        -Enable color and formatting in output to make compiler errors easier to read.
        -
        -// @reactNamespace
        -Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
        -
        -// @removeComments
        -Disable emitting comments..
        -
        -// @resolveJsonModule
        -Enable importing .json files.
        -
        -// @rootDir
        -Specify the root folder within your source files..
        -
        -// @rootDirs
        -Allow multiple folders to be treated as one when resolving modules..
        -
        -// @skipDefaultLibCheck
        -Skip type checking .d.ts files that are included with TypeScript..
        -
        -// @skipLibCheck
        -Skip type checking all .d.ts files..
        -
        -// @sourceMap
        -Create source map files for emitted JavaScript files..
        -
        -// @sourceRoot
        -Specify the root path for debuggers to find the reference source code..
        -
        -// @strict
        -Enable all strict type-checking options..
        -
        -// @strictBindCallApply
        -Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
        -
        -// @strictFunctionTypes
        -When assigning functions, check to ensure parameters and the return values are subtype-compatible..
        -
        -// @strictNullChecks
        -When type checking, take into account `null` and `undefined`..
        -
        -// @strictPropertyInitialization
        -Check for class properties that are declared but not set in the constructor..
        -
        -// @stripInternal
        -Disable emitting declarations that have `@internal` in their JSDoc comments..
        -
        -// @suppressExcessPropertyErrors
        -Disable reporting of excess property errors during the creation of object literals..
        -
        -// @suppressImplicitAnyIndexErrors
        -Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
        -
        -// @target
        -Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
        -
        -// @traceResolution
        -Log paths used during the `moduleResolution` process..
        -
        -// @tsBuildInfoFile
        -Specify the folder for .tsbuildinfo incremental compilation files..
        -
        -// @typeRoots
        -Specify multiple folders that act like `./node_modules/@types`..
        -
        -// @types
        -Specify type package names to be included without being referenced in a source file..
        -
        -// @useDefineForClassFields
        -Emit ECMAScript-standard-compliant class fields..
        -
        -// @useUnknownInCatchVariables
        -Type catch clause variables as 'unknown' instead of 'any'..
        // @allowJs
        -Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
        -
        -// @allowSyntheticDefaultImports
        -Allow 'import x from y' when a module doesn't have a default export..
        -
        -// @allowUmdGlobalAccess
        -Allow accessing UMD globals from modules..
        -
        -// @allowUnreachableCode
        -Disable error reporting for unreachable code..
        -
        -// @allowUnusedLabels
        -Disable error reporting for unused labels..
        -
        -// @alwaysStrict
        -Ensure 'use strict' is always emitted..
        -
        -// @assumeChangesOnlyAffectDirectDependencies
        -Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
        -
        -// @baseUrl
        -Specify the base directory to resolve non-relative module names..
        -
        -// @charset
        -No longer supported. In early versions, manually set the text encoding for reading files..
        -
        -// @checkJs
        -Enable error reporting in type-checked JavaScript files..
        -
        -// @composite
        -Enable constraints that allow a TypeScript project to be used with project references..
        -
        -// @declaration
        -Generate .d.ts files from TypeScript and JavaScript files in your project..
        -
        -// @declarationDir
        -Specify the output directory for generated declaration files..
        -
        -// @declarationMap
        -Create sourcemaps for d.ts files..
        -
        -// @diagnostics
        -Output compiler performance information after building..
        -
        -// @disableReferencedProjectLoad
        -Reduce the number of projects loaded automatically by TypeScript..
        -
        -// @disableSizeLimit
        -Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
        -
        -// @disableSolutionSearching
        -Opt a project out of multi-project reference checking when editing..
        -
        -// @disableSourceOfProjectReferenceRedirect
        -Disable preferring source files instead of declaration files when referencing composite projects.
        -
        -// @downlevelIteration
        -Emit more compliant, but verbose and less performant JavaScript for iteration..
        -
        -// @emitBOM
        -Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
        -
        -// @emitDeclarationOnly
        -Only output d.ts files and not JavaScript files..
        -
        -// @emitDecoratorMetadata
        -Emit design-type metadata for decorated declarations in source files..
        -
        -// @esModuleInterop
        -Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
        -
        -// @exactOptionalPropertyTypes
        -Interpret optional property types as written, rather than adding 'undefined'..
        -
        -// @experimentalDecorators
        -Enable experimental support for TC39 stage 2 draft decorators..
        -
        -// @explainFiles
        -Print files read during the compilation including why it was included..
        -
        -// @extendedDiagnostics
        -Output more detailed compiler performance information after building..
        -
        -// @forceConsistentCasingInFileNames
        -Ensure that casing is correct in imports..
        -
        -// @generateCpuProfile
        -Emit a v8 CPU profile of the compiler run for debugging..
        -
        -// @importHelpers
        -Allow importing helper functions from tslib once per project, instead of including them per-file..
        -
        -// @importsNotUsedAsValues
        -Specify emit/checking behavior for imports that are only used for types.
        -
        -// @incremental
        -Enable incremental compilation.
        -
        -// @inlineSourceMap
        -Include sourcemap files inside the emitted JavaScript..
        -
        -// @inlineSources
        -Include source code in the sourcemaps inside the emitted JavaScript..
        -
        -// @isolatedModules
        -Ensure that each file can be safely transpiled without relying on other imports..
        -
        -// @jsx
        -Specify what JSX code is generated..
        -
        -// @jsxFactory
        -Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
        -
        -// @jsxFragmentFactory
        -Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
        -
        -// @jsxImportSource
        -Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
        -
        -// @keyofStringsOnly
        -Make keyof only return strings instead of string, numbers or symbols. Legacy option..
        -
        -// @lib
        -Specify a set of bundled library declaration files that describe the target runtime environment..
        -
        -// @listEmittedFiles
        -Print the names of emitted files after a compilation..
        -
        -// @listFiles
        -Print all of the files read during the compilation..
        -
        -// @mapRoot
        -Specify the location where debugger should locate map files instead of generated locations..
        -
        -// @maxNodeModuleJsDepth
        -Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
        -
        -// @module
        -Specify what module code is generated..
        -
        -// @moduleResolution
        -Specify how TypeScript looks up a file from a given module specifier..
        -
        -// @newLine
        -Set the newline character for emitting files..
        -
        -// @noEmit
        -Disable emitting file from a compilation..
        -
        -// @noEmitHelpers
        -Disable generating custom helper functions like `__extends` in compiled output..
        -
        -// @noEmitOnError
        -Disable emitting files if any type checking errors are reported..
        -
        -// @noErrorTruncation
        -Disable truncating types in error messages..
        -
        -// @noFallthroughCasesInSwitch
        -Enable error reporting for fallthrough cases in switch statements..
        -
        -// @noImplicitAny
        -Enable error reporting for expressions and declarations with an implied `any` type...
        -
        -// @noImplicitOverride
        -Add `undefined` to a type when accessed using an index..
        -
        -// @noImplicitReturns
        -Enable error reporting for codepaths that do not explicitly return in a function..
        -
        -// @noImplicitThis
        -Enable error reporting when `this` is given the type `any`..
        -
        -// @noImplicitUseStrict
        -Disable adding 'use strict' directives in emitted JavaScript files..
        -
        -// @noLib
        -Disable including any library files, including the default lib.d.ts..
        -
        -// @noPropertyAccessFromIndexSignature
        -Enforces using indexed accessors for keys declared using an indexed type.
        -
        -// @noResolve
        -Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
        -
        -// @noStrictGenericChecks
        -Disable strict checking of generic signatures in function types..
        -
        -// @noUncheckedIndexedAccess
        -Include 'undefined' in index signature results.
        -
        -// @noUnusedLocals
        -Enable error reporting when a local variables aren't read..
        -
        -// @noUnusedParameters
        -Raise an error when a function parameter isn't read.
        -
        -// @out
        -Deprecated setting. Use `outFile` instead..
        -
        -// @outDir
        -Specify an output folder for all emitted files..
        -
        -// @outFile
        -Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
        -
        -// @paths
        -Specify a set of entries that re-map imports to additional lookup locations..
        -
        -// @plugins
        -List of language service plugins..
        -
        -// @preserveConstEnums
        -Disable erasing `const enum` declarations in generated code..
        -
        -// @preserveSymlinks
        -Disable resolving symlinks to their realpath. This correlates to the same flag in node..
        -
        -// @preserveWatchOutput
        -Disable wiping the console in watch mode.
        -
        -// @pretty
        -Enable color and formatting in output to make compiler errors easier to read.
        -
        -// @reactNamespace
        -Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
        -
        -// @removeComments
        -Disable emitting comments..
        -
        -// @resolveJsonModule
        -Enable importing .json files.
        -
        -// @rootDir
        -Specify the root folder within your source files..
        -
        -// @rootDirs
        -Allow multiple folders to be treated as one when resolving modules..
        -
        -// @skipDefaultLibCheck
        -Skip type checking .d.ts files that are included with TypeScript..
        -
        -// @skipLibCheck
        -Skip type checking all .d.ts files..
        -
        -// @sourceMap
        -Create source map files for emitted JavaScript files..
        -
        -// @sourceRoot
        -Specify the root path for debuggers to find the reference source code..
        -
        -// @strict
        -Enable all strict type-checking options..
        -
        -// @strictBindCallApply
        -Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
        -
        -// @strictFunctionTypes
        -When assigning functions, check to ensure parameters and the return values are subtype-compatible..
        -
        -// @strictNullChecks
        -When type checking, take into account `null` and `undefined`..
        -
        -// @strictPropertyInitialization
        -Check for class properties that are declared but not set in the constructor..
        -
        -// @stripInternal
        -Disable emitting declarations that have `@internal` in their JSDoc comments..
        -
        -// @suppressExcessPropertyErrors
        -Disable reporting of excess property errors during the creation of object literals..
        -
        -// @suppressImplicitAnyIndexErrors
        -Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
        -
        -// @target
        -Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
        -
        -// @traceResolution
        -Log paths used during the `moduleResolution` process..
        -
        -// @tsBuildInfoFile
        -Specify the folder for .tsbuildinfo incremental compilation files..
        -
        -// @typeRoots
        -Specify multiple folders that act like `./node_modules/@types`..
        -
        -// @types
        -Specify type package names to be included without being referenced in a source file..
        -
        -// @useDefineForClassFields
        -Emit ECMAScript-standard-compliant class fields..
        -
        -// @useUnknownInCatchVariables
        -Type catch clause variables as 'unknown' instead of 'any'..
        +
        // @allowJs
        +Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
        +
        +// @allowSyntheticDefaultImports
        +Allow 'import x from y' when a module doesn't have a default export..
        +
        +// @allowUmdGlobalAccess
        +Allow accessing UMD globals from modules..
        +
        +// @allowUnreachableCode
        +Disable error reporting for unreachable code..
        +
        +// @allowUnusedLabels
        +Disable error reporting for unused labels..
        +
        +// @alwaysStrict
        +Ensure 'use strict' is always emitted..
        +
        +// @assumeChangesOnlyAffectDirectDependencies
        +Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
        +
        +// @baseUrl
        +Specify the base directory to resolve non-relative module names..
        +
        +// @charset
        +No longer supported. In early versions, manually set the text encoding for reading files..
        +
        +// @checkJs
        +Enable error reporting in type-checked JavaScript files..
        +
        +// @composite
        +Enable constraints that allow a TypeScript project to be used with project references..
        +
        +// @declaration
        +Generate .d.ts files from TypeScript and JavaScript files in your project..
        +
        +// @declarationDir
        +Specify the output directory for generated declaration files..
        +
        +// @declarationMap
        +Create sourcemaps for d.ts files..
        +
        +// @diagnostics
        +Output compiler performance information after building..
        +
        +// @disableReferencedProjectLoad
        +Reduce the number of projects loaded automatically by TypeScript..
        +
        +// @disableSizeLimit
        +Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
        +
        +// @disableSolutionSearching
        +Opt a project out of multi-project reference checking when editing..
        +
        +// @disableSourceOfProjectReferenceRedirect
        +Disable preferring source files instead of declaration files when referencing composite projects.
        +
        +// @downlevelIteration
        +Emit more compliant, but verbose and less performant JavaScript for iteration..
        +
        +// @emitBOM
        +Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
        +
        +// @emitDeclarationOnly
        +Only output d.ts files and not JavaScript files..
        +
        +// @emitDecoratorMetadata
        +Emit design-type metadata for decorated declarations in source files..
        +
        +// @esModuleInterop
        +Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
        +
        +// @exactOptionalPropertyTypes
        +Interpret optional property types as written, rather than adding 'undefined'..
        +
        +// @experimentalDecorators
        +Enable experimental support for TC39 stage 2 draft decorators..
        +
        +// @explainFiles
        +Print files read during the compilation including why it was included..
        +
        +// @extendedDiagnostics
        +Output more detailed compiler performance information after building..
        +
        +// @forceConsistentCasingInFileNames
        +Ensure that casing is correct in imports..
        +
        +// @generateCpuProfile
        +Emit a v8 CPU profile of the compiler run for debugging..
        +
        +// @importHelpers
        +Allow importing helper functions from tslib once per project, instead of including them per-file..
        +
        +// @importsNotUsedAsValues
        +Specify emit/checking behavior for imports that are only used for types.
        +
        +// @incremental
        +Enable incremental compilation.
        +
        +// @inlineSourceMap
        +Include sourcemap files inside the emitted JavaScript..
        +
        +// @inlineSources
        +Include source code in the sourcemaps inside the emitted JavaScript..
        +
        +// @isolatedModules
        +Ensure that each file can be safely transpiled without relying on other imports..
        +
        +// @jsx
        +Specify what JSX code is generated..
        +
        +// @jsxFactory
        +Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
        +
        +// @jsxFragmentFactory
        +Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
        +
        +// @jsxImportSource
        +Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
        +
        +// @keyofStringsOnly
        +Make keyof only return strings instead of string, numbers or symbols. Legacy option..
        +
        +// @lib
        +Specify a set of bundled library declaration files that describe the target runtime environment..
        +
        +// @listEmittedFiles
        +Print the names of emitted files after a compilation..
        +
        +// @listFiles
        +Print all of the files read during the compilation..
        +
        +// @mapRoot
        +Specify the location where debugger should locate map files instead of generated locations..
        +
        +// @maxNodeModuleJsDepth
        +Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
        +
        +// @module
        +Specify what module code is generated..
        +
        +// @moduleResolution
        +Specify how TypeScript looks up a file from a given module specifier..
        +
        +// @newLine
        +Set the newline character for emitting files..
        +
        +// @noEmit
        +Disable emitting file from a compilation..
        +
        +// @noEmitHelpers
        +Disable generating custom helper functions like `__extends` in compiled output..
        +
        +// @noEmitOnError
        +Disable emitting files if any type checking errors are reported..
        +
        +// @noErrorTruncation
        +Disable truncating types in error messages..
        +
        +// @noFallthroughCasesInSwitch
        +Enable error reporting for fallthrough cases in switch statements..
        +
        +// @noImplicitAny
        +Enable error reporting for expressions and declarations with an implied `any` type...
        +
        +// @noImplicitOverride
        +Add `undefined` to a type when accessed using an index..
        +
        +// @noImplicitReturns
        +Enable error reporting for codepaths that do not explicitly return in a function..
        +
        +// @noImplicitThis
        +Enable error reporting when `this` is given the type `any`..
        +
        +// @noImplicitUseStrict
        +Disable adding 'use strict' directives in emitted JavaScript files..
        +
        +// @noLib
        +Disable including any library files, including the default lib.d.ts..
        +
        +// @noPropertyAccessFromIndexSignature
        +Enforces using indexed accessors for keys declared using an indexed type.
        +
        +// @noResolve
        +Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
        +
        +// @noStrictGenericChecks
        +Disable strict checking of generic signatures in function types..
        +
        +// @noUncheckedIndexedAccess
        +Include 'undefined' in index signature results.
        +
        +// @noUnusedLocals
        +Enable error reporting when a local variables aren't read..
        +
        +// @noUnusedParameters
        +Raise an error when a function parameter isn't read.
        +
        +// @out
        +Deprecated setting. Use `outFile` instead..
        +
        +// @outDir
        +Specify an output folder for all emitted files..
        +
        +// @outFile
        +Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
        +
        +// @paths
        +Specify a set of entries that re-map imports to additional lookup locations..
        +
        +// @plugins
        +List of language service plugins..
        +
        +// @preserveConstEnums
        +Disable erasing `const enum` declarations in generated code..
        +
        +// @preserveSymlinks
        +Disable resolving symlinks to their realpath. This correlates to the same flag in node..
        +
        +// @preserveWatchOutput
        +Disable wiping the console in watch mode.
        +
        +// @pretty
        +Enable color and formatting in output to make compiler errors easier to read.
        +
        +// @reactNamespace
        +Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
        +
        +// @removeComments
        +Disable emitting comments..
        +
        +// @resolveJsonModule
        +Enable importing .json files.
        +
        +// @rootDir
        +Specify the root folder within your source files..
        +
        +// @rootDirs
        +Allow multiple folders to be treated as one when resolving modules..
        +
        +// @skipDefaultLibCheck
        +Skip type checking .d.ts files that are included with TypeScript..
        +
        +// @skipLibCheck
        +Skip type checking all .d.ts files..
        +
        +// @sourceMap
        +Create source map files for emitted JavaScript files..
        +
        +// @sourceRoot
        +Specify the root path for debuggers to find the reference source code..
        +
        +// @strict
        +Enable all strict type-checking options..
        +
        +// @strictBindCallApply
        +Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
        +
        +// @strictFunctionTypes
        +When assigning functions, check to ensure parameters and the return values are subtype-compatible..
        +
        +// @strictNullChecks
        +When type checking, take into account `null` and `undefined`..
        +
        +// @strictPropertyInitialization
        +Check for class properties that are declared but not set in the constructor..
        +
        +// @stripInternal
        +Disable emitting declarations that have `@internal` in their JSDoc comments..
        +
        +// @suppressExcessPropertyErrors
        +Disable reporting of excess property errors during the creation of object literals..
        +
        +// @suppressImplicitAnyIndexErrors
        +Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
        +
        +// @target
        +Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
        +
        +// @traceResolution
        +Log paths used during the `moduleResolution` process..
        +
        +// @tsBuildInfoFile
        +Specify the folder for .tsbuildinfo incremental compilation files..
        +
        +// @typeRoots
        +Specify multiple folders that act like `./node_modules/@types`..
        +
        +// @types
        +Specify type package names to be included without being referenced in a source file..
        +
        +// @useDefineForClassFields
        +Emit ECMAScript-standard-compliant class fields..
        +
        +// @useUnknownInCatchVariables
        +Type catch clause variables as 'unknown' instead of 'any'..
        // @allowJs
        +Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
        +
        +// @allowSyntheticDefaultImports
        +Allow 'import x from y' when a module doesn't have a default export..
        +
        +// @allowUmdGlobalAccess
        +Allow accessing UMD globals from modules..
        +
        +// @allowUnreachableCode
        +Disable error reporting for unreachable code..
        +
        +// @allowUnusedLabels
        +Disable error reporting for unused labels..
        +
        +// @alwaysStrict
        +Ensure 'use strict' is always emitted..
        +
        +// @assumeChangesOnlyAffectDirectDependencies
        +Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
        +
        +// @baseUrl
        +Specify the base directory to resolve non-relative module names..
        +
        +// @charset
        +No longer supported. In early versions, manually set the text encoding for reading files..
        +
        +// @checkJs
        +Enable error reporting in type-checked JavaScript files..
        +
        +// @composite
        +Enable constraints that allow a TypeScript project to be used with project references..
        +
        +// @declaration
        +Generate .d.ts files from TypeScript and JavaScript files in your project..
        +
        +// @declarationDir
        +Specify the output directory for generated declaration files..
        +
        +// @declarationMap
        +Create sourcemaps for d.ts files..
        +
        +// @diagnostics
        +Output compiler performance information after building..
        +
        +// @disableReferencedProjectLoad
        +Reduce the number of projects loaded automatically by TypeScript..
        +
        +// @disableSizeLimit
        +Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
        +
        +// @disableSolutionSearching
        +Opt a project out of multi-project reference checking when editing..
        +
        +// @disableSourceOfProjectReferenceRedirect
        +Disable preferring source files instead of declaration files when referencing composite projects.
        +
        +// @downlevelIteration
        +Emit more compliant, but verbose and less performant JavaScript for iteration..
        +
        +// @emitBOM
        +Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
        +
        +// @emitDeclarationOnly
        +Only output d.ts files and not JavaScript files..
        +
        +// @emitDecoratorMetadata
        +Emit design-type metadata for decorated declarations in source files..
        +
        +// @esModuleInterop
        +Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
        +
        +// @exactOptionalPropertyTypes
        +Interpret optional property types as written, rather than adding 'undefined'..
        +
        +// @experimentalDecorators
        +Enable experimental support for TC39 stage 2 draft decorators..
        +
        +// @explainFiles
        +Print files read during the compilation including why it was included..
        +
        +// @extendedDiagnostics
        +Output more detailed compiler performance information after building..
        +
        +// @forceConsistentCasingInFileNames
        +Ensure that casing is correct in imports..
        +
        +// @generateCpuProfile
        +Emit a v8 CPU profile of the compiler run for debugging..
        +
        +// @importHelpers
        +Allow importing helper functions from tslib once per project, instead of including them per-file..
        +
        +// @importsNotUsedAsValues
        +Specify emit/checking behavior for imports that are only used for types.
        +
        +// @incremental
        +Enable incremental compilation.
        +
        +// @inlineSourceMap
        +Include sourcemap files inside the emitted JavaScript..
        +
        +// @inlineSources
        +Include source code in the sourcemaps inside the emitted JavaScript..
        +
        +// @isolatedModules
        +Ensure that each file can be safely transpiled without relying on other imports..
        +
        +// @jsx
        +Specify what JSX code is generated..
        +
        +// @jsxFactory
        +Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
        +
        +// @jsxFragmentFactory
        +Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
        +
        +// @jsxImportSource
        +Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
        +
        +// @keyofStringsOnly
        +Make keyof only return strings instead of string, numbers or symbols. Legacy option..
        +
        +// @lib
        +Specify a set of bundled library declaration files that describe the target runtime environment..
        +
        +// @listEmittedFiles
        +Print the names of emitted files after a compilation..
        +
        +// @listFiles
        +Print all of the files read during the compilation..
        +
        +// @mapRoot
        +Specify the location where debugger should locate map files instead of generated locations..
        +
        +// @maxNodeModuleJsDepth
        +Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
        +
        +// @module
        +Specify what module code is generated..
        +
        +// @moduleResolution
        +Specify how TypeScript looks up a file from a given module specifier..
        +
        +// @newLine
        +Set the newline character for emitting files..
        +
        +// @noEmit
        +Disable emitting file from a compilation..
        +
        +// @noEmitHelpers
        +Disable generating custom helper functions like `__extends` in compiled output..
        +
        +// @noEmitOnError
        +Disable emitting files if any type checking errors are reported..
        +
        +// @noErrorTruncation
        +Disable truncating types in error messages..
        +
        +// @noFallthroughCasesInSwitch
        +Enable error reporting for fallthrough cases in switch statements..
        +
        +// @noImplicitAny
        +Enable error reporting for expressions and declarations with an implied `any` type...
        +
        +// @noImplicitOverride
        +Add `undefined` to a type when accessed using an index..
        +
        +// @noImplicitReturns
        +Enable error reporting for codepaths that do not explicitly return in a function..
        +
        +// @noImplicitThis
        +Enable error reporting when `this` is given the type `any`..
        +
        +// @noImplicitUseStrict
        +Disable adding 'use strict' directives in emitted JavaScript files..
        +
        +// @noLib
        +Disable including any library files, including the default lib.d.ts..
        +
        +// @noPropertyAccessFromIndexSignature
        +Enforces using indexed accessors for keys declared using an indexed type.
        +
        +// @noResolve
        +Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
        +
        +// @noStrictGenericChecks
        +Disable strict checking of generic signatures in function types..
        +
        +// @noUncheckedIndexedAccess
        +Include 'undefined' in index signature results.
        +
        +// @noUnusedLocals
        +Enable error reporting when a local variables aren't read..
        +
        +// @noUnusedParameters
        +Raise an error when a function parameter isn't read.
        +
        +// @out
        +Deprecated setting. Use `outFile` instead..
        +
        +// @outDir
        +Specify an output folder for all emitted files..
        +
        +// @outFile
        +Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
        +
        +// @paths
        +Specify a set of entries that re-map imports to additional lookup locations..
        +
        +// @plugins
        +List of language service plugins..
        +
        +// @preserveConstEnums
        +Disable erasing `const enum` declarations in generated code..
        +
        +// @preserveSymlinks
        +Disable resolving symlinks to their realpath. This correlates to the same flag in node..
        +
        +// @preserveWatchOutput
        +Disable wiping the console in watch mode.
        +
        +// @pretty
        +Enable color and formatting in output to make compiler errors easier to read.
        +
        +// @reactNamespace
        +Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
        +
        +// @removeComments
        +Disable emitting comments..
        +
        +// @resolveJsonModule
        +Enable importing .json files.
        +
        +// @rootDir
        +Specify the root folder within your source files..
        +
        +// @rootDirs
        +Allow multiple folders to be treated as one when resolving modules..
        +
        +// @skipDefaultLibCheck
        +Skip type checking .d.ts files that are included with TypeScript..
        +
        +// @skipLibCheck
        +Skip type checking all .d.ts files..
        +
        +// @sourceMap
        +Create source map files for emitted JavaScript files..
        +
        +// @sourceRoot
        +Specify the root path for debuggers to find the reference source code..
        +
        +// @strict
        +Enable all strict type-checking options..
        +
        +// @strictBindCallApply
        +Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
        +
        +// @strictFunctionTypes
        +When assigning functions, check to ensure parameters and the return values are subtype-compatible..
        +
        +// @strictNullChecks
        +When type checking, take into account `null` and `undefined`..
        +
        +// @strictPropertyInitialization
        +Check for class properties that are declared but not set in the constructor..
        +
        +// @stripInternal
        +Disable emitting declarations that have `@internal` in their JSDoc comments..
        +
        +// @suppressExcessPropertyErrors
        +Disable reporting of excess property errors during the creation of object literals..
        +
        +// @suppressImplicitAnyIndexErrors
        +Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
        +
        +// @target
        +Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
        +
        +// @traceResolution
        +Log paths used during the `moduleResolution` process..
        +
        +// @tsBuildInfoFile
        +Specify the folder for .tsbuildinfo incremental compilation files..
        +
        +// @typeRoots
        +Specify multiple folders that act like `./node_modules/@types`..
        +
        +// @types
        +Specify type package names to be included without being referenced in a source file..
        +
        +// @useDefineForClassFields
        +Emit ECMAScript-standard-compliant class fields..
        +
        +// @useUnknownInCatchVariables
        +Type catch clause variables as 'unknown' instead of 'any'..
        ]]> @@ -22822,8 +22822,8 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3 Config

        Overview

        You can configure VitePress Twoslash using the twoslash property added to defineConfig.

        -
        ts
        ts
        // .vitepress/config.[ext]
        import { defineConfig } from 'vitepress'
        import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
         
        export default withTwoslash(
        defineConfig({
        twoslash: {
        // Your VitePress Twoslash options
        },
        })
        )
        -
        ts
        // .vitepress/config.[ext]
        import { defineConfig } from 'vitepress'
        import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
         
        export default withTwoslash(
        defineConfig({
        twoslash: {
        // Your VitePress Twoslash options
        },
        })
        )
        +
        ts
        ts
        // .vitepress/config.[ext]
        import { defineConfig } from 'vitepress'
        import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
         
        export default withTwoslash(
        defineConfig({
        twoslash: {
        // Your VitePress Twoslash options
        },
        })
        )
        +
        ts
        // .vitepress/config.[ext]
        import { defineConfig } from 'vitepress'
        import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
         
        export default withTwoslash(
        defineConfig({
        twoslash: {
        // Your VitePress Twoslash options
        },
        })
        )

        INFO

        In addition to the below config options, VitePress Twoslash also supports all shiki HighlighterOptions and @typescript/twoslash TwoSlashOptions.

        @@ -22834,120 +22834,120 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3
      • Type: boolean
      • Default: false
      -
      ts
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            addTryButton: true, 
      -        },
      -    })
      -)
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            addTryButton: true, 
      -        },
      -    })
      -)
      +
      ts
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            addTryButton: true, 
      +        },
      +    })
      +)
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            addTryButton: true, 
      +        },
      +    })
      +)

      alwayRaiseForTwoslashExceptions

      Instead of showing twoslash exceptions inline, throw the entire process like it will on CI.

      • Type: boolean
      • Default: false
      -
      ts
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            alwayRaiseForTwoslashExceptions: true, 
      -        },
      -    })
      -)
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            alwayRaiseForTwoslashExceptions: true, 
      -        },
      -    })
      -)
      +
      ts
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            alwayRaiseForTwoslashExceptions: true, 
      +        },
      +    })
      +)
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            alwayRaiseForTwoslashExceptions: true, 
      +        },
      +    })
      +)

      disableImplicitReactImport

      A way to disable implicit React imports on tsx/jsx language codeblocks

      • Type: boolean
      • Default: false
      -
      ts
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            disableImplicitReactImport: true, 
      -        },
      -    })
      -)
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            disableImplicitReactImport: true, 
      -        },
      -    })
      -)
      +
      ts
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            disableImplicitReactImport: true, 
      +        },
      +    })
      +)
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            disableImplicitReactImport: true, 
      +        },
      +    })
      +)

      includeJSDocInHover

      Include JSDoc comments in the hovers.

      • Type: boolean
      • Default: false
      -
      ts
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            includeJSDocInHover: true, 
      -        },
      -    })
      -)
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            includeJSDocInHover: true, 
      -        },
      -    })
      -)
      +
      ts
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            includeJSDocInHover: true, 
      +        },
      +    })
      +)
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            includeJSDocInHover: true, 
      +        },
      +    })
      +)

      ignoreCodeblocksWithCodefenceMeta

      Ignore transforming certain code blocks.

      • Type: boolean
      • Default: false
      -
      ts
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            ignoreCodeblocksWithCodefenceMeta: true, 
      -        },
      -    })
      -)
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            ignoreCodeblocksWithCodefenceMeta: true, 
      -        },
      -    })
      -)
      +
      ts
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            ignoreCodeblocksWithCodefenceMeta: true, 
      +        },
      +    })
      +)
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            ignoreCodeblocksWithCodefenceMeta: true, 
      +        },
      +    })
      +)

      wrapFragments

      A way to add a div wrapper for multi-theme outputs.

      • Type: boolean
      • Default: false
      -
      ts
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            wrapFragments: true, 
      -        },
      -    })
      -)
      export default withTwoslash(
      -    defineConfig({
      -        twoslash: {
      -            wrapFragments: true, 
      -        },
      -    })
      -)
      +
      ts
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            wrapFragments: true, 
      +        },
      +    })
      +)
      export default withTwoslash(
      +    defineConfig({
      +        twoslash: {
      +            wrapFragments: true, 
      +        },
      +    })
      +)
      ]]> Config

      Overview

      You can configure VitePress Twoslash using the twoslash property added to defineConfig.

      -
      ts
      ts
      // .vitepress/config.[ext]
      import { defineConfig } from 'vitepress'
      import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
       
      export default withTwoslash(
      defineConfig({
      twoslash: {
      // Your VitePress Twoslash options
      },
      })
      )
      -
      ts
      // .vitepress/config.[ext]
      import { defineConfig } from 'vitepress'
      import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
       
      export default withTwoslash(
      defineConfig({
      twoslash: {
      // Your VitePress Twoslash options
      },
      })
      )
      +
      ts
      ts
      // .vitepress/config.[ext]
      import { defineConfig } from 'vitepress'
      import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
       
      export default withTwoslash(
      defineConfig({
      twoslash: {
      // Your VitePress Twoslash options
      },
      })
      )
      +
      ts
      // .vitepress/config.[ext]
      import { defineConfig } from 'vitepress'
      import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
       
      export default withTwoslash(
      defineConfig({
      twoslash: {
      // Your VitePress Twoslash options
      },
      })
      )

      INFO

      In addition to the below config options, VitePress Twoslash also supports all shiki HighlighterOptions and @typescript/twoslash TwoSlashOptions.

      @@ -22958,114 +22958,114 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3
    • Type: boolean
    • Default: false
    -
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            addTryButton: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            addTryButton: true, 
    -        },
    -    })
    -)
    +
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            addTryButton: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            addTryButton: true, 
    +        },
    +    })
    +)

    alwayRaiseForTwoslashExceptions

    Instead of showing twoslash exceptions inline, throw the entire process like it will on CI.

    • Type: boolean
    • Default: false
    -
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            alwayRaiseForTwoslashExceptions: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            alwayRaiseForTwoslashExceptions: true, 
    -        },
    -    })
    -)
    +
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            alwayRaiseForTwoslashExceptions: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            alwayRaiseForTwoslashExceptions: true, 
    +        },
    +    })
    +)

    disableImplicitReactImport

    A way to disable implicit React imports on tsx/jsx language codeblocks

    • Type: boolean
    • Default: false
    -
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            disableImplicitReactImport: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            disableImplicitReactImport: true, 
    -        },
    -    })
    -)
    +
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            disableImplicitReactImport: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            disableImplicitReactImport: true, 
    +        },
    +    })
    +)

    includeJSDocInHover

    Include JSDoc comments in the hovers.

    • Type: boolean
    • Default: false
    -
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            includeJSDocInHover: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            includeJSDocInHover: true, 
    -        },
    -    })
    -)
    +
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            includeJSDocInHover: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            includeJSDocInHover: true, 
    +        },
    +    })
    +)

    ignoreCodeblocksWithCodefenceMeta

    Ignore transforming certain code blocks.

    • Type: boolean
    • Default: false
    -
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            ignoreCodeblocksWithCodefenceMeta: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            ignoreCodeblocksWithCodefenceMeta: true, 
    -        },
    -    })
    -)
    +
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            ignoreCodeblocksWithCodefenceMeta: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            ignoreCodeblocksWithCodefenceMeta: true, 
    +        },
    +    })
    +)

    wrapFragments

    A way to add a div wrapper for multi-theme outputs.

    • Type: boolean
    • Default: false
    -
    ts
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            wrapFragments: true, 
    -        },
    -    })
    -)
    export default withTwoslash(
    -    defineConfig({
    -        twoslash: {
    -            wrapFragments: true, 
    -        },
    -    })
    -)
    +
    ts
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            wrapFragments: true, 
    +        },
    +    })
    +)
    export default withTwoslash(
    +    defineConfig({
    +        twoslash: {
    +            wrapFragments: true, 
    +        },
    +    })
    +)
    ]]> @@ -23077,189 +23077,189 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3

    Twoslash uses your markdown.theme for syntax highlighting, but there are a few other things you can do to customize the look and feel of your code examples — particulary the generated Twoslash interface.

    CSS Variables

    The following CSS variables (and their defaults) are available to style Twoslash interface:

    -
    css
    :root {
    -    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
    +
    css
    :root {
    +    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
     
    -    --vp-twoslash-c-brand: var(--vp-c-brand);
    +    --vp-twoslash-c-brand: var(--vp-c-brand);
     
    -    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
     
    -    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    -    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    -    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    -    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    -    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
    +    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    +    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    +    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    +    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    +    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
     
    -    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    -    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    -    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    -    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
    +    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    +    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    +    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    +    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
     
    -    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    -    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    -    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    -}
    :root {
    -    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    +    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    +    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    +}
    :root {
    +    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
     
    -    --vp-twoslash-c-brand: var(--vp-c-brand);
    +    --vp-twoslash-c-brand: var(--vp-c-brand);
     
    -    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
     
    -    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    -    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    -    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    -    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    -    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
    +    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    +    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    +    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    +    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    +    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
     
    -    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    -    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    -    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    -    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
    +    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    +    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    +    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    +    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
     
    -    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    -    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    -    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    -}
    + --vp-twoslash-c-query-bg: var(--vp-c-mute-darker); + --vp-twoslash-c-query-fg-2: var(--vp-c-text-2); + --vp-twoslash-c-query-fg: var(--vp-c-text-1); +}

    Dark/Light Theme

    If you pass a responsive theme to markdown.theme, you probably also want to hide/show the correct theme based on the user's settings.

    -
    ts
    ts
    export default defineConfig({
    markdown: {
    theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
    },
    })
    -
    ts
    export default defineConfig({
    markdown: {
    theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
    },
    })
    +
    ts
    ts
    export default defineConfig({
    markdown: {
    theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
    },
    })
    +
    ts
    export default defineConfig({
    markdown: {
    theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
    },
    })

    You can do this with the following CSS:

    -
    css
    /*
    - * Hide block based on theme
    - * `[class*='-dark']` matches `'vitesse-dark'`
    - * `[class*='-light']` matches `'vitesse-light'`
    - */
    -html:not(.dark) pre.shiki[class*='-dark'] {
    -    display: none;
    -}
    -html:not(.dark) pre.shiki[class*='-light'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-dark'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-light'] {
    -    display: none;
    -}
    /*
    - * Hide block based on theme
    - * `[class*='-dark']` matches `'vitesse-dark'`
    - * `[class*='-light']` matches `'vitesse-light'`
    - */
    -html:not(.dark) pre.shiki[class*='-dark'] {
    -    display: none;
    -}
    -html:not(.dark) pre.shiki[class*='-light'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-dark'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-light'] {
    -    display: none;
    -}
    +
    css
    /*
    + * Hide block based on theme
    + * `[class*='-dark']` matches `'vitesse-dark'`
    + * `[class*='-light']` matches `'vitesse-light'`
    + */
    +html:not(.dark) pre.shiki[class*='-dark'] {
    +    display: none;
    +}
    +html:not(.dark) pre.shiki[class*='-light'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-dark'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-light'] {
    +    display: none;
    +}
    /*
    + * Hide block based on theme
    + * `[class*='-dark']` matches `'vitesse-dark'`
    + * `[class*='-light']` matches `'vitesse-light'`
    + */
    +html:not(.dark) pre.shiki[class*='-dark'] {
    +    display: none;
    +}
    +html:not(.dark) pre.shiki[class*='-light'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-dark'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-light'] {
    +    display: none;
    +}
    ]]> Using a Custom Theme

    Twoslash uses your markdown.theme for syntax highlighting, but there are a few other things you can do to customize the look and feel of your code examples — particulary the generated Twoslash interface.

    CSS Variables

    The following CSS variables (and their defaults) are available to style Twoslash interface:

    -
    css
    :root {
    -    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
    +
    css
    :root {
    +    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
     
    -    --vp-twoslash-c-brand: var(--vp-c-brand);
    +    --vp-twoslash-c-brand: var(--vp-c-brand);
     
    -    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
     
    -    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    -    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    -    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    -    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    -    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
    +    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    +    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    +    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    +    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    +    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
     
    -    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    -    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    -    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    -    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
    +    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    +    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    +    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    +    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
     
    -    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    -    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    -    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    -}
    :root {
    -    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    +    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    +    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    +}
    :root {
    +    --vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
     
    -    --vp-twoslash-c-brand: var(--vp-c-brand);
    +    --vp-twoslash-c-brand: var(--vp-c-brand);
     
    -    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-error-fg: var(--vp-c-text-1);
     
    -    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    -    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    -    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    -    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    -    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    -    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
    +    --vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
    +    --vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
    +    --vp-twoslash-c-logger-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
    +    --vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
    +    --vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
    +    --vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
     
    -    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    -    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    -    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    -    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    -    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
    +    --vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
    +    --vp-twoslash-c-lsp-border: var(--vp-c-divider);
    +    --vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
    +    --vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
    +    --vp-twoslash-lsp-shadow: var(--vp-shadow-2);
     
    -    --vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
    -    --vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
    -    --vp-twoslash-c-query-fg: var(--vp-c-text-1);
    -}
    + --vp-twoslash-c-query-bg: var(--vp-c-mute-darker); + --vp-twoslash-c-query-fg-2: var(--vp-c-text-2); + --vp-twoslash-c-query-fg: var(--vp-c-text-1); +}

    Dark/Light Theme

    If you pass a responsive theme to markdown.theme, you probably also want to hide/show the correct theme based on the user's settings.

    -
    ts
    ts
    export default defineConfig({
    markdown: {
    theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
    },
    })
    -
    ts
    export default defineConfig({
    markdown: {
    theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
    },
    })
    +
    ts
    ts
    export default defineConfig({
    markdown: {
    theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
    },
    })
    +
    ts
    export default defineConfig({
    markdown: {
    theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
    },
    })

    You can do this with the following CSS:

    -
    css
    /*
    - * Hide block based on theme
    - * `[class*='-dark']` matches `'vitesse-dark'`
    - * `[class*='-light']` matches `'vitesse-light'`
    - */
    -html:not(.dark) pre.shiki[class*='-dark'] {
    -    display: none;
    -}
    -html:not(.dark) pre.shiki[class*='-light'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-dark'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-light'] {
    -    display: none;
    -}
    /*
    - * Hide block based on theme
    - * `[class*='-dark']` matches `'vitesse-dark'`
    - * `[class*='-light']` matches `'vitesse-light'`
    - */
    -html:not(.dark) pre.shiki[class*='-dark'] {
    -    display: none;
    -}
    -html:not(.dark) pre.shiki[class*='-light'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-dark'] {
    -    display: block;
    -}
    -html.dark pre.shiki[class*='-light'] {
    -    display: none;
    -}
    +
    css
    /*
    + * Hide block based on theme
    + * `[class*='-dark']` matches `'vitesse-dark'`
    + * `[class*='-light']` matches `'vitesse-light'`
    + */
    +html:not(.dark) pre.shiki[class*='-dark'] {
    +    display: none;
    +}
    +html:not(.dark) pre.shiki[class*='-light'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-dark'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-light'] {
    +    display: none;
    +}
    /*
    + * Hide block based on theme
    + * `[class*='-dark']` matches `'vitesse-dark'`
    + * `[class*='-light']` matches `'vitesse-light'`
    + */
    +html:not(.dark) pre.shiki[class*='-dark'] {
    +    display: none;
    +}
    +html:not(.dark) pre.shiki[class*='-light'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-dark'] {
    +    display: block;
    +}
    +html.dark pre.shiki[class*='-light'] {
    +    display: none;
    +}
    ]]> @@ -23270,13 +23270,13 @@ c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3 Markdown Extensions

    Code Groups

    Code Groups and Twoslash multi-file support.

    -
    -
    ts
    ts
    import { name } from './name'
    export function hello(name: string) {
    console.log(`Hello, ${name}!`)
    }
    hello(name)
    (alias) const name: "twoslash" +
    +
    ts
    ts
    import { name } from './name'
    export function hello(name: string) {
    console.log(`Hello, ${name}!`)
    }
    hello(name)
    (alias) const name: "twoslash" import name
    -
    ts
    import { name } from './name'
    export function hello(name: string) {
    console.log(`Hello, ${name}!`)
    }
    hello(name)
    (alias) const name: "twoslash" +
    ts
    import { name } from './name'
    export function hello(name: string) {
    console.log(`Hello, ${name}!`)
    }
    hello(name)
    (alias) const name: "twoslash" import name
    -
    ts
    ts
    export const name = 'twoslash'
    -
    ts
    export const name = 'twoslash'
    +
    ts
    ts
    export const name = 'twoslash'
    +
    ts
    export const name = 'twoslash'

    Unsupported Extensions

    Since VitePress Twoslash uses it's own Shiki highlighter, the following syntax highlighting extensions are not currently compatible.

    @@ -23293,13 +23293,13 @@ import name
    Markdown Extensions

    Code Groups

    Code Groups and Twoslash multi-file support.

    -
    -
    ts
    ts
    import { name } from './name'
    export function hello(name: string) {
    console.log(`Hello, ${name}!`)
    }
    hello(name)
    (alias) const name: "twoslash" +
    +
    ts
    ts
    import { name } from './name'
    export function hello(name: string) {
    console.log(`Hello, ${name}!`)
    }
    hello(name)
    (alias) const name: "twoslash" import name
    -
    ts
    import { name } from './name'
    export function hello(name: string) {
    console.log(`Hello, ${name}!`)
    }
    hello(name)
    (alias) const name: "twoslash" +
    ts
    import { name } from './name'
    export function hello(name: string) {
    console.log(`Hello, ${name}!`)
    }
    hello(name)
    (alias) const name: "twoslash" import name
    -
    ts
    ts
    export const name = 'twoslash'
    -
    ts
    export const name = 'twoslash'
    +
    ts
    ts
    export const name = 'twoslash'
    +
    ts
    export const name = 'twoslash'

    Unsupported Extensions

    Since VitePress Twoslash uses it's own Shiki highlighter, the following syntax highlighting extensions are not currently compatible.

    @@ -23325,83 +23325,83 @@ import name

    Overview

    Try moving your cursor into the code block below:

    -
    ts
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    -
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    +
    ts
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    +
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>

    Pretty neat, right? To some extent, anything your editor can show you about code, Twoslash can show. For example, here is the real auto-complete for a VitePress config:

    -
    ts
    ts
    import { defineConfig } from 'vitepress'
     
    export default defineConfig({
    ti,
          
    })
    -
    ts
    import { defineConfig } from 'vitepress'
     
    export default defineConfig({
    ti,
          
    })
    +
    ts
    ts
    import { defineConfig } from 'vitepress'
     
    export default defineConfig({
    ti,
          
    })
    +
    ts
    import { defineConfig } from 'vitepress'
     
    export default defineConfig({
    ti,
          
    })

    The name Twoslash refers to specially formatted comments (e.g. // ^?) which can be used to set up your environment, like compiler flags or separate input files. It couldn't be easier to set up and start creating incredible code examples!

    Install

    Install @andatoshiki/vitepress-plugin-shiki-twoslash (requires vitepress@>=1.0.0-alpha.61).

    -
    -
    bash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    -
    bash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    -
    bash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
    +
    +
    bash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    +
    bash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    +
    bash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash

    WARNING

    Until shiki-twoslash uses the same version of shiki as VitePress, you must override the following packages' shiki versions for syntax highlighting to look the same.

    -
    json
    {
    -    "pnpm": {
    -        "overrides": {
    -            "remark-shiki-twoslash>shiki": "^0.14.1",
    -            "shiki-twoslash>shiki": "^0.14.1"
    -        }
    -    }
    -}
    {
    -    "pnpm": {
    -        "overrides": {
    -            "remark-shiki-twoslash>shiki": "^0.14.1",
    -            "shiki-twoslash>shiki": "^0.14.1"
    -        }
    -    }
    -}
    +
    json
    {
    +    "pnpm": {
    +        "overrides": {
    +            "remark-shiki-twoslash>shiki": "^0.14.1",
    +            "shiki-twoslash>shiki": "^0.14.1"
    +        }
    +    }
    +}
    {
    +    "pnpm": {
    +        "overrides": {
    +            "remark-shiki-twoslash>shiki": "^0.14.1",
    +            "shiki-twoslash>shiki": "^0.14.1"
    +        }
    +    }
    +}

    Tracked in an upstream issue: https://github.com/shikijs/twoslash/issues/180

    Configure

    First, wrap your VitePress config file with the withTwoslash wrapper.

    -
    ts
    ts
    // .vitepress/config.[ext]
    import { defineConfig } from 'vitepress'
    import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
     
    export default withTwoslash(
    defineConfig({
    // Your VitePress config
    })
    )
    -
    ts
    // .vitepress/config.[ext]
    import { defineConfig } from 'vitepress'
    import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
     
    export default withTwoslash(
    defineConfig({
    // Your VitePress config
    })
    )
    +
    ts
    ts
    // .vitepress/config.[ext]
    import { defineConfig } from 'vitepress'
    import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
     
    export default withTwoslash(
    defineConfig({
    // Your VitePress config
    })
    )
    +
    ts
    // .vitepress/config.[ext]
    import { defineConfig } from 'vitepress'
    import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
     
    export default withTwoslash(
    defineConfig({
    // Your VitePress config
    })
    )

    Then, import @andatoshiki/vitepress-plugin-shiki-twoslash/styles.css into your theme.

    -
    ts
    ts
    // .vitepress/theme/index.ts
    import defaultTheme from 'vitepress/theme'
    import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
     
    export default defaultTheme
    -
    ts
    // .vitepress/theme/index.ts
    import defaultTheme from 'vitepress/theme'
    import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
     
    export default defaultTheme
    +
    ts
    ts
    // .vitepress/theme/index.ts
    import defaultTheme from 'vitepress/theme'
    import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
     
    export default defaultTheme
    +
    ts
    // .vitepress/theme/index.ts
    import defaultTheme from 'vitepress/theme'
    import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
     
    export default defaultTheme

    TIP

    You can configure VitePress Twoslash using the twoslash property added to defineConfig.

    Add Twoslash

    Finally, add the twoslash attribute to markdown fenced code blocks.

    -
    md
    ```ts twoslash
    -// Removes 'readonly' attributes from a type's properties
    -type CreateMutable<Type> = {
    -    -readonly [Property in keyof Type]: Type[Property]
    -}
    +
    md
    ```ts twoslash
    +// Removes 'readonly' attributes from a type's properties
    +type CreateMutable<Type> = {
    +    -readonly [Property in keyof Type]: Type[Property]
    +}
     
    -type LockedAccount = {
    -    readonly id: string
    -    readonly name: string
    -}
    +type LockedAccount = {
    +    readonly id: string
    +    readonly name: string
    +}
     
    -type UnlockedAccount = CreateMutable<LockedAccount>
    -//   ^?
    -```
    ```ts twoslash
    -// Removes 'readonly' attributes from a type's properties
    -type CreateMutable<Type> = {
    -    -readonly [Property in keyof Type]: Type[Property]
    -}
    +type UnlockedAccount = CreateMutable<LockedAccount>
    +//   ^?
    +```
    ```ts twoslash
    +// Removes 'readonly' attributes from a type's properties
    +type CreateMutable<Type> = {
    +    -readonly [Property in keyof Type]: Type[Property]
    +}
     
    -type LockedAccount = {
    -    readonly id: string
    -    readonly name: string
    -}
    +type LockedAccount = {
    +    readonly id: string
    +    readonly name: string
    +}
     
    -type UnlockedAccount = CreateMutable<LockedAccount>
    -//   ^?
    -```
    +type UnlockedAccount = CreateMutable<LockedAccount> +// ^? +```

    And your code blocks will be twoslashified!

    -
    ts
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    type UnlockedAccount = { +
    ts
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    type UnlockedAccount = { id: string; name: string; }
    -
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    type UnlockedAccount = { +
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    type UnlockedAccount = { id: string; name: string; }
    @@ -23412,83 +23412,83 @@ import name

    Overview

    Try moving your cursor into the code block below:

    -
    ts
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    -
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    +
    ts
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    +
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>

    Pretty neat, right? To some extent, anything your editor can show you about code, Twoslash can show. For example, here is the real auto-complete for a VitePress config:

    -
    ts
    ts
    import { defineConfig } from 'vitepress'
     
    export default defineConfig({
    ti,
          
    })
    -
    ts
    import { defineConfig } from 'vitepress'
     
    export default defineConfig({
    ti,
          
    })
    +
    ts
    ts
    import { defineConfig } from 'vitepress'
     
    export default defineConfig({
    ti,
          
    })
    +
    ts
    import { defineConfig } from 'vitepress'
     
    export default defineConfig({
    ti,
          
    })

    The name Twoslash refers to specially formatted comments (e.g. // ^?) which can be used to set up your environment, like compiler flags or separate input files. It couldn't be easier to set up and start creating incredible code examples!

    Install

    Install @andatoshiki/vitepress-plugin-shiki-twoslash (requires vitepress@>=1.0.0-alpha.61).

    -
    -
    bash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    -
    bash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    -
    bash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
    +
    +
    bash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
    +
    bash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    npm i @andatoshiki/vitepress-plugin-shiki-twoslash
    +
    bash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
    yarn add @andatoshiki/vitepress-plugin-shiki-twoslash

    WARNING

    Until shiki-twoslash uses the same version of shiki as VitePress, you must override the following packages' shiki versions for syntax highlighting to look the same.

    -
    json
    {
    -    "pnpm": {
    -        "overrides": {
    -            "remark-shiki-twoslash>shiki": "^0.14.1",
    -            "shiki-twoslash>shiki": "^0.14.1"
    -        }
    -    }
    -}
    {
    -    "pnpm": {
    -        "overrides": {
    -            "remark-shiki-twoslash>shiki": "^0.14.1",
    -            "shiki-twoslash>shiki": "^0.14.1"
    -        }
    -    }
    -}
    +
    json
    {
    +    "pnpm": {
    +        "overrides": {
    +            "remark-shiki-twoslash>shiki": "^0.14.1",
    +            "shiki-twoslash>shiki": "^0.14.1"
    +        }
    +    }
    +}
    {
    +    "pnpm": {
    +        "overrides": {
    +            "remark-shiki-twoslash>shiki": "^0.14.1",
    +            "shiki-twoslash>shiki": "^0.14.1"
    +        }
    +    }
    +}

    Tracked in an upstream issue: https://github.com/shikijs/twoslash/issues/180

    Configure

    First, wrap your VitePress config file with the withTwoslash wrapper.

    -
    ts
    ts
    // .vitepress/config.[ext]
    import { defineConfig } from 'vitepress'
    import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
     
    export default withTwoslash(
    defineConfig({
    // Your VitePress config
    })
    )
    -
    ts
    // .vitepress/config.[ext]
    import { defineConfig } from 'vitepress'
    import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
     
    export default withTwoslash(
    defineConfig({
    // Your VitePress config
    })
    )
    +
    ts
    ts
    // .vitepress/config.[ext]
    import { defineConfig } from 'vitepress'
    import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
     
    export default withTwoslash(
    defineConfig({
    // Your VitePress config
    })
    )
    +
    ts
    // .vitepress/config.[ext]
    import { defineConfig } from 'vitepress'
    import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
     
    export default withTwoslash(
    defineConfig({
    // Your VitePress config
    })
    )

    Then, import @andatoshiki/vitepress-plugin-shiki-twoslash/styles.css into your theme.

    -
    ts
    ts
    // .vitepress/theme/index.ts
    import defaultTheme from 'vitepress/theme'
    import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
     
    export default defaultTheme
    -
    ts
    // .vitepress/theme/index.ts
    import defaultTheme from 'vitepress/theme'
    import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
     
    export default defaultTheme
    +
    ts
    ts
    // .vitepress/theme/index.ts
    import defaultTheme from 'vitepress/theme'
    import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
     
    export default defaultTheme
    +
    ts
    // .vitepress/theme/index.ts
    import defaultTheme from 'vitepress/theme'
    import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
     
    export default defaultTheme

    TIP

    You can configure VitePress Twoslash using the twoslash property added to defineConfig.

    Add Twoslash

    Finally, add the twoslash attribute to markdown fenced code blocks.

    -
    md
    ```ts twoslash
    -// Removes 'readonly' attributes from a type's properties
    -type CreateMutable<Type> = {
    -    -readonly [Property in keyof Type]: Type[Property]
    -}
    +
    md
    ```ts twoslash
    +// Removes 'readonly' attributes from a type's properties
    +type CreateMutable<Type> = {
    +    -readonly [Property in keyof Type]: Type[Property]
    +}
     
    -type LockedAccount = {
    -    readonly id: string
    -    readonly name: string
    -}
    +type LockedAccount = {
    +    readonly id: string
    +    readonly name: string
    +}
     
    -type UnlockedAccount = CreateMutable<LockedAccount>
    -//   ^?
    -```
    ```ts twoslash
    -// Removes 'readonly' attributes from a type's properties
    -type CreateMutable<Type> = {
    -    -readonly [Property in keyof Type]: Type[Property]
    -}
    +type UnlockedAccount = CreateMutable<LockedAccount>
    +//   ^?
    +```
    ```ts twoslash
    +// Removes 'readonly' attributes from a type's properties
    +type CreateMutable<Type> = {
    +    -readonly [Property in keyof Type]: Type[Property]
    +}
     
    -type LockedAccount = {
    -    readonly id: string
    -    readonly name: string
    -}
    +type LockedAccount = {
    +    readonly id: string
    +    readonly name: string
    +}
     
    -type UnlockedAccount = CreateMutable<LockedAccount>
    -//   ^?
    -```
    +type UnlockedAccount = CreateMutable<LockedAccount> +// ^? +```

    And your code blocks will be twoslashified!

    -
    ts
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    type UnlockedAccount = { +
    ts
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    type UnlockedAccount = { id: string; name: string; }
    -
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    type UnlockedAccount = { +
    ts
    // Removes 'readonly' attributes from a type's properties
    type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property]
    }
     
    type LockedAccount = {
    readonly id: string
    readonly name: string
    }
     
    type UnlockedAccount = CreateMutable<LockedAccount>
    type UnlockedAccount = { id: string; name: string; }
    @@ -23638,11 +23638,11 @@ import name

    続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

    -
    toml
    [default]
    -    region = us-east-1
    -    output = json
    [default]
    -    region = us-east-1
    -    output = json
    +
    toml
    [default]
    +    region = us-east-1
    +    output = json
    [default]
    +    region = us-east-1
    +    output = json
    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).
    @@ -23650,59 +23650,59 @@ import name

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    -
    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    +
    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    -
    sh
    $ aws --version
    $ aws --version
    +
    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    -
    sh
    $ aws configure
    $ aws configure
    +
    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    -
    sh
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +
    sh
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
     
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
     
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    +$ cat ~/.aws/config +[profile default] +region = ap-northeast-1 +output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    -
    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile
    +
    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    -
    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile
    +
    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    -
    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    +
    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    -
    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk
    +
    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    -
    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100
    +
    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    -
    sh
    $ cdk --version
    $ cdk --version
    +
    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    -
    sh
    $ cdk bootstrap
    $ cdk bootstrap
    +
    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    @@ -23713,15 +23713,15 @@ import name

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    -
    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    +
    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    -
    powershell
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    +
    powershell
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    -
    powershell
    wsl --set-default-version 2
    wsl --set-default-version 2
    +
    powershell
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    @@ -23737,33 +23737,33 @@ import name

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    -
    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh
    +
    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    -
    sh
    $ sudo groupadd docker
    $ sudo groupadd docker
    +
    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    -
    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER
    +
    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    -
    sh
    $ docker run hello-world
    $ docker run hello-world
    +
    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    -
    sh
    $ python -m venv .env
    $ python -m venv .env
    +
    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    -
    sh
    $ source .env/bin/activate
    $ source .env/bin/activate
    +
    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    -
    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt
    +
    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    @@ -23771,16 +23771,16 @@ import name

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    -
    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest
    +
    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    root@aws-handson:~$</programlisting>

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    -
    sh
    $ cd handson
    $ cd handson
    +
    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい ( (#sec_handson_ec2_run) など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    -
    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    +
    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    ]]> @@ -23869,11 +23869,11 @@ import name

    続いて, ~/.aws/config というファイルを用意し,次の内容を書き込む. 現時点では AWS Starter Account は us-east-1 リージョンでしか利用できないためである.

    -
    toml
    [default]
    -    region = us-east-1
    -    output = json
    [default]
    -    region = us-east-1
    -    output = json
    +
    toml
    [default]
    +    region = us-east-1
    +    output = json
    [default]
    +    region = us-east-1
    +    output = json
    • 上記の説明ではプロファイル名が default となっていたが,これは自分の好きな名前に変更してもよい. default 以外の名前を使用する場合は,コマンドを実行するときにプロファイル名を指定する必要がある (詳しくは AWS CLI のインストール).
    @@ -23881,59 +23881,59 @@ import name

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    -
    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    +
    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    -
    sh
    $ aws --version
    $ aws --version
    +
    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    -
    sh
    $ aws configure
    $ aws configure
    +
    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    -
    sh
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +
    sh
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
     
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
     
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    +$ cat ~/.aws/config +[profile default] +region = ap-northeast-1 +output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    -
    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile
    +
    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    -
    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile
    +
    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    -
    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    +
    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    -
    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk
    +
    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    -
    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100
    +
    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    -
    sh
    $ cdk --version
    $ cdk --version
    +
    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    -
    sh
    $ cdk bootstrap
    $ cdk bootstrap
    +
    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    @@ -23944,15 +23944,15 @@ import name

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    -
    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    +
    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    -
    powershell
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    +
    powershell
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    -
    powershell
    wsl --set-default-version 2
    wsl --set-default-version 2
    +
    powershell
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    @@ -23968,33 +23968,33 @@ import name

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    -
    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh
    +
    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    -
    sh
    $ sudo groupadd docker
    $ sudo groupadd docker
    +
    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    -
    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER
    +
    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    -
    sh
    $ docker run hello-world
    $ docker run hello-world
    +
    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    -
    sh
    $ python -m venv .env
    $ python -m venv .env
    +
    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    -
    sh
    $ source .env/bin/activate
    $ source .env/bin/activate
    +
    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    -
    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt
    +
    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    @@ -24002,16 +24002,16 @@ import name

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    -
    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest
    +
    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    root@aws-handson:~$</programlisting>

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    -
    sh
    $ cd handson
    $ cd handson
    +
    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい ( (#sec_handson_ec2_run) など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    -
    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    +
    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    ]]> @@ -24079,7 +24079,7 @@ import name

    (#sec:jupyter_and_deep_learning_setup) でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, (#sec_mnist_using_jupyter) で扱った MNIST 手書き文字認識の問題を再度取り上げよう. (#sec_mnist_using_jupyter) では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    -
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    +
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    @@ -24090,14 +24090,14 @@ import name

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に (#sec_mnist_using_jupyter) のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    -
    sh
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    +
    sh
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    -
    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest
    +
    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    -
    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    +
    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. (#sec_jupyter_and_deep_learning) のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    @@ -24136,163 +24136,163 @@ import name

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    -
    python
    class SimpleBatch(core.Stack):
    +
    python
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    class SimpleBatch(core.Stack):
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    + # + job_def = batch.JobDefinition( + self, "job-definition", + container=batch.JobDefinitionContainer( + image=ecs.ContainerImage.from_ecr_repository(repo), + command=["python3", "main.py"], + vcpus=4, + gpu_count=1, + memory_limit_mib=12000, + job_role=job_role, + environment={ + "BUCKET_NAME": bucket.bucket_name + } + ), + job_definition_name=self.stack_name + "job-definition", + timeout=core.Duration.hours(2), + )
    • で,計算結果を保存するための S3 バケットを用意している

      @@ -24319,25 +24319,25 @@ import name

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    @@ -24347,33 +24347,33 @@ import name

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン ( (#sec_fargate_qabot)) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    -
    python
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    +
    python
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
     
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
     
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    +job_def = batch.JobDefinition( + self, "job-definition", + container=batch.JobDefinitionContainer( + image=ecs.ContainerImage.from_ecr_repository(repo), # + ... + ), + ... +)
    • で,新規の ECR を作成している.

      @@ -24395,89 +24395,89 @@ import name

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    -
    sh
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    +
    sh
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    -
    python
    # [1]
    -import boto3
    -import argparse
    +
    python
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
     
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    -import boto3
    -import argparse
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
     
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    + title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "") + resp = client.submit_job( + jobName=title, + jobQueue="SimpleBatchjob-queue", + jobDefinition="SimpleBatchjob-definition", + containerOverrides={ + "command": ["--lr", str(lr), + "--momentum", str(momentum), + "--epochs", str(epochs), + "--uploadS3", "true"] + } + ) + print("Job submitted!") + print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    -
    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    +
    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    -
    python
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    +
    python
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    -
    python
    # [4]
    -submit_job(0.01, 0.1, 100)
    # [4]
    -submit_job(0.01, 0.1, 100)
    +
    python
    # [4]
    +submit_job(0.01, 0.1, 100)
    # [4]
    +submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは (#aws_cli_install)), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    @@ -24489,124 +24489,124 @@ import name

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    -
    python
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    +
    python
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    +# [7] +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu" +df = read_table_from_s3( + bucket_name, + "metrics_lr0.0100_m0.1000.csv" +)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    -
    python
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    +
    python
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
     
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
     
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
     
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
     
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
     
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
     
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    +print("Best loss:", df["val_loss"].min()) +print("Best loss epoch:", df["val_loss"].argmin()) +print("Best accuracy:", df["val_accuracy"].max()) +print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    -
    python
    # [1]
    -import boto3
    -import argparse
    +
    python
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    # [1]
    -import boto3
    -import argparse
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    +# [3] +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None): + # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    -
    python
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    +
    python
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    @@ -24616,81 +24616,81 @@ import name

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    -
    python
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    +
    python
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
     
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
     
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
     
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
     
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
     
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
     
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    +for i in range(3): + for j in range(3): + text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}", + ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    @@ -24703,9 +24703,9 @@ import name

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    -
    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    +
    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, (#sec_jupyter_and_deep_learning) で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを (#sec_fargate_qabot) を参考に構築する.

    @@ -24746,7 +24746,7 @@ import name

    (#sec:jupyter_and_deep_learning_setup) でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, (#sec_mnist_using_jupyter) で扱った MNIST 手書き文字認識の問題を再度取り上げよう. (#sec_mnist_using_jupyter) では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    -
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    +
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    @@ -24757,14 +24757,14 @@ import name

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に (#sec_mnist_using_jupyter) のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    -
    sh
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    +
    sh
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    -
    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest
    +
    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    -
    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    +
    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. (#sec_jupyter_and_deep_learning) のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    @@ -24803,163 +24803,163 @@ import name

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    -
    python
    class SimpleBatch(core.Stack):
    +
    python
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    class SimpleBatch(core.Stack):
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    + # + job_def = batch.JobDefinition( + self, "job-definition", + container=batch.JobDefinitionContainer( + image=ecs.ContainerImage.from_ecr_repository(repo), + command=["python3", "main.py"], + vcpus=4, + gpu_count=1, + memory_limit_mib=12000, + job_role=job_role, + environment={ + "BUCKET_NAME": bucket.bucket_name + } + ), + job_definition_name=self.stack_name + "job-definition", + timeout=core.Duration.hours(2), + )
    • で,計算結果を保存するための S3 バケットを用意している

      @@ -24986,25 +24986,25 @@ import name

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    @@ -25014,33 +25014,33 @@ import name

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン ( (#sec_fargate_qabot)) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    -
    python
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    +
    python
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
     
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
     
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    +job_def = batch.JobDefinition( + self, "job-definition", + container=batch.JobDefinitionContainer( + image=ecs.ContainerImage.from_ecr_repository(repo), # + ... + ), + ... +)
    • で,新規の ECR を作成している.

      @@ -25062,89 +25062,89 @@ import name

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    -
    sh
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    +
    sh
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    -
    python
    # [1]
    -import boto3
    -import argparse
    +
    python
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
     
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    -import boto3
    -import argparse
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
     
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    + title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "") + resp = client.submit_job( + jobName=title, + jobQueue="SimpleBatchjob-queue", + jobDefinition="SimpleBatchjob-definition", + containerOverrides={ + "command": ["--lr", str(lr), + "--momentum", str(momentum), + "--epochs", str(epochs), + "--uploadS3", "true"] + } + ) + print("Job submitted!") + print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    -
    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    +
    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    -
    python
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    +
    python
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    -
    python
    # [4]
    -submit_job(0.01, 0.1, 100)
    # [4]
    -submit_job(0.01, 0.1, 100)
    +
    python
    # [4]
    +submit_job(0.01, 0.1, 100)
    # [4]
    +submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは (#aws_cli_install)), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    @@ -25156,124 +25156,124 @@ import name

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    -
    python
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    +
    python
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    +# [7] +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu" +df = read_table_from_s3( + bucket_name, + "metrics_lr0.0100_m0.1000.csv" +)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    -
    python
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    +
    python
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
     
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
     
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
     
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
     
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
     
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
     
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    +print("Best loss:", df["val_loss"].min()) +print("Best loss epoch:", df["val_loss"].argmin()) +print("Best accuracy:", df["val_accuracy"].max()) +print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    -
    python
    # [1]
    -import boto3
    -import argparse
    +
    python
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    # [1]
    -import boto3
    -import argparse
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    +# [3] +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None): + # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    -
    python
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    +
    python
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    @@ -25283,81 +25283,81 @@ import name

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    -
    python
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    +
    python
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
     
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
     
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
     
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
     
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
     
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
     
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    +for i in range(3): + for j in range(3): + text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}", + ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    @@ -25370,9 +25370,9 @@ import name

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    -
    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    +
    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, (#sec_jupyter_and_deep_learning) で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを (#sec_fargate_qabot) を参考に構築する.

    @@ -25456,44 +25456,44 @@ import name

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    -
    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    +
    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    -
    python
    import boto3
    +
    python
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    +s3_client = boto3.client("s3", region_name="ap-northeast-1") +s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    -
    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    +
    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン ( (#sec_first_ec2)) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    -
    python
    import boto3
    +
    python
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    import boto3
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    +ec2_client = boto3.client("ec2") +ec2_client.run_instances( + ImageId="ami-xxxxxxxxx", + MinCount=1, + MaxCount=1, + KeyName="MyKeyPair", + InstanceType="t2.micro", + SecurityGroupIds=["sg-903004f8"], + SubnetId="subnet-6e7f829e", +)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    @@ -25501,34 +25501,34 @@ import name

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは (#aws_cli_install) を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    -
    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    +
    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    -
    sh
    $ aws s3 ls
    +
    sh
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    -
    sh
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    +
    sh
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    -
    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +
    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    +2020-06-07 23:54:19 13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    -
    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force
    +
    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    @@ -25544,120 +25544,120 @@ import name

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    -
    json
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +
    json
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    + "/opt/aws/bin/cfn-signal -e $? ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WebServer ", + " --region ", { "Ref" : "AWS::Region" }, "\n" + ]]}} + }, + ... + }, + ... +},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    -
    python
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +
    python
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    + host = ec2.Instance( + self, "MyGreatEc2", + instance_type=ec2.InstanceType("t2.micro"), + machine_image=ec2.MachineImage.latest_amazon_linux(), + vpc=vpc, + ... + )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

      @@ -25729,44 +25729,44 @@ import name

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    -
    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    +
    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    -
    python
    import boto3
    +
    python
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    +s3_client = boto3.client("s3", region_name="ap-northeast-1") +s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    -
    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    +
    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン ( (#sec_first_ec2)) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    -
    python
    import boto3
    +
    python
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    import boto3
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    +ec2_client = boto3.client("ec2") +ec2_client.run_instances( + ImageId="ami-xxxxxxxxx", + MinCount=1, + MaxCount=1, + KeyName="MyKeyPair", + InstanceType="t2.micro", + SecurityGroupIds=["sg-903004f8"], + SubnetId="subnet-6e7f829e", +)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    @@ -25774,34 +25774,34 @@ import name

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは (#aws_cli_install) を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    -
    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    +
    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    -
    sh
    $ aws s3 ls
    +
    sh
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    -
    sh
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    +
    sh
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    -
    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +
    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    +2020-06-07 23:54:19 13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    -
    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force
    +
    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    @@ -25817,120 +25817,120 @@ import name

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    -
    json
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +
    json
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    + "/opt/aws/bin/cfn-signal -e $? ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WebServer ", + " --region ", { "Ref" : "AWS::Region" }, "\n" + ]]}} + }, + ... + }, + ... +},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    -
    python
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +
    python
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    + host = ec2.Instance( + self, "MyGreatEc2", + instance_type=ec2.InstanceType("t2.micro"), + machine_image=ec2.MachineImage.latest_amazon_linux(), + vpc=vpc, + ... + )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

      @@ -26150,92 +26150,92 @@ import name

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    -
    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04
    +
    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    -
    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04
    +
    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, (#sec_jupyter_and_deep_learning) でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    -
    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch
    +
    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    -
    sh
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    +
    sh
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    -
    dockerfile
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +
    dockerfile
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \
    -    && apt-get install nano
    +RUN apt-get update \
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
     
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +# copy hands-on source code in /root/
    +COPY handson/ /root/handson
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \
    -    && apt-get install nano
    +RUN apt-get update \
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
     
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    +# copy hands-on source code in /root/ +COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    @@ -26288,92 +26288,92 @@ import name

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    -
    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04
    +
    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    -
    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04
    +
    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, (#sec_jupyter_and_deep_learning) でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    -
    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch
    +
    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    -
    sh
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    +
    sh
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    -
    dockerfile
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +
    dockerfile
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \
    -    && apt-get install nano
    +RUN apt-get update \
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
     
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +# copy hands-on source code in /root/
    +COPY handson/ /root/handson
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \
    -    && apt-get install nano
    +RUN apt-get update \
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
     
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    +# copy hands-on source code in /root/ +COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    @@ -26432,197 +26432,197 @@ import name

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    -
    python
    class Bashoutter(core.Stack):
    +
    python
    class Bashoutter(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
     
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
     
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
     
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
     
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
     
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    class Bashoutter(core.Stack):
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    class Bashoutter(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
     
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
     
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
     
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
     
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
     
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    + haiku_item_id = haiku.add_resource("{item_id}") + haiku_item_id.add_method( + "PATCH", + apigw.LambdaIntegration(patch_haiku_lambda) + ) + haiku_item_id.add_method( + "DELETE", + apigw.LambdaIntegration(delete_haiku_lambda) + )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

      @@ -26643,17 +26643,17 @@ import name

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    -
    python
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    +
    python
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    @@ -26664,72 +26664,72 @@ import name

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    -
    python
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    +
    python
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    -
    python
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    +
    python
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
     
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
     
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
     
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
     
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    + status_code = 200 + resp = response.get("Items") + except Exception as e: + status_code = 500 + resp = {"description": f"Internal server error. {str(e)}"} + return { + "statusCode": status_code, + "headers": HEADERS, + "body": json.dumps(resp, cls=DecimalEncoder) + }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    -
    python
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    +
    python
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は (#sec_aws_batch) で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    @@ -26740,69 +26740,69 @@ import name

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    -
    python
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    +
    python
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
     
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
     
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
     
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
     
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    +# +haiku_item_id = haiku.add_resource("{item_id}") +# +haiku_item_id.add_method( + "PATCH", + apigw.LambdaIntegration(patch_haiku_lambda) +) +haiku_item_id.add_method( + "DELETE", + apigw.LambdaIntegration(delete_haiku_lambda) +)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

      @@ -26825,25 +26825,25 @@ import name

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    @@ -26859,109 +26859,109 @@ import name

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    -
    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX
    +
    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    -
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"
    +
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    -
    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"
    +
    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"

    次のような出力が得られるだろう.

    -
    sh
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    +
    sh
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    -
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
     
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
     
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    +HTTP/1.1 200 OK +Connection: keep-alive +Content-Length: 258 +Content-Type: application/json +... +[ + { + "created_at": "2020-07-06T02:46:04+00:00", + "first": "閑さや", + "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b", + "likes": 0.0, + "second": "岩にしみ入る", + "third": "蝉の声", + "username": "松尾芭蕉" + } +]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    -
    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    +
    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    -
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    +
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    -
    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    +
    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    -
    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300
    +
    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    -
    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database
    +
    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている ( (#fig:web_server) 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    -
    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    +
    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    @@ -26973,11 +26973,11 @@ import name

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    -
    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive
    +
    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. (#sec_intro_serverless) では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    @@ -27018,197 +27018,197 @@ import name

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    -
    python
    class Bashoutter(core.Stack):
    +
    python
    class Bashoutter(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
     
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
     
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
     
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
     
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
     
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    class Bashoutter(core.Stack):
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    class Bashoutter(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
     
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
     
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
     
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
     
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
     
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    + haiku_item_id = haiku.add_resource("{item_id}") + haiku_item_id.add_method( + "PATCH", + apigw.LambdaIntegration(patch_haiku_lambda) + ) + haiku_item_id.add_method( + "DELETE", + apigw.LambdaIntegration(delete_haiku_lambda) + )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

      @@ -27229,17 +27229,17 @@ import name

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    -
    python
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    +
    python
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    @@ -27250,72 +27250,72 @@ import name

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    -
    python
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    +
    python
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    -
    python
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    +
    python
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
     
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
     
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
     
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
     
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    + status_code = 200 + resp = response.get("Items") + except Exception as e: + status_code = 500 + resp = {"description": f"Internal server error. {str(e)}"} + return { + "statusCode": status_code, + "headers": HEADERS, + "body": json.dumps(resp, cls=DecimalEncoder) + }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    -
    python
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    +
    python
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は (#sec_aws_batch) で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    @@ -27326,69 +27326,69 @@ import name

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    -
    python
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    +
    python
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
     
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
     
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
     
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
     
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    +# +haiku_item_id = haiku.add_resource("{item_id}") +# +haiku_item_id.add_method( + "PATCH", + apigw.LambdaIntegration(patch_haiku_lambda) +) +haiku_item_id.add_method( + "DELETE", + apigw.LambdaIntegration(delete_haiku_lambda) +)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

      @@ -27411,25 +27411,25 @@ import name

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    @@ -27445,109 +27445,109 @@ import name

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    -
    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX
    +
    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    -
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"
    +
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    -
    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"
    +
    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"

    次のような出力が得られるだろう.

    -
    sh
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    +
    sh
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    -
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
     
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
     
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    +HTTP/1.1 200 OK +Connection: keep-alive +Content-Length: 258 +Content-Type: application/json +... +[ + { + "created_at": "2020-07-06T02:46:04+00:00", + "first": "閑さや", + "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b", + "likes": 0.0, + "second": "岩にしみ入る", + "third": "蝉の声", + "username": "松尾芭蕉" + } +]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    -
    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    +
    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    -
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    +
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    -
    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    +
    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    -
    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300
    +
    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    -
    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database
    +
    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている ( (#fig:web_server) 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    -
    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    +
    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    @@ -27559,11 +27559,11 @@ import name

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    -
    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive
    +
    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. (#sec_intro_serverless) では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    @@ -27598,7 +27598,7 @@ import name

    ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.

    -
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    +
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    @@ -27607,95 +27607,95 @@ import name

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する ( (#environments) を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    -
    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>
    +
    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    -
    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    +
    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    -
    python
    class MyFirstEc2(core.Stack):
    +
    python
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class MyFirstEc2(core.Stack):
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    + # + host = ec2.Instance( + self, "MyFirstEc2Instance", + instance_type=ec2.InstanceType("t2.micro"), + machine_image=ec2.MachineImage.latest_amazon_linux(), + vpc=vpc, + vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC), + security_group=sg, + key_name=key_name + )
    • まず最初に,VPC を定義する.

      @@ -27714,29 +27714,29 @@ import name

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    -
    python
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    +
    python
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

      @@ -27754,23 +27754,23 @@ import name

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    -
    python
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    +
    python
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    @@ -27840,23 +27840,23 @@ import name

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    -
    python
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    +
    python
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, (#sec_jupyter_and_deep_learning) でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    @@ -27864,13 +27864,13 @@ import name

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    -
    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started
    +
    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    -
    sh
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +
    sh
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は (#venv_quick_guide) に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    @@ -27880,21 +27880,21 @@ import name

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    -
    sh
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +
    sh
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    -
    sh
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +
    sh
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    -
    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"
    +
    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    -
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    +
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    @@ -27902,69 +27902,69 @@ import name

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    -
    sh
    $ cat /proc/cpuinfo
    +
    sh
    $ cat /proc/cpuinfo
     
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    $ cat /proc/cpuinfo
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB
    $ cat /proc/cpuinfo
     
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    +processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 63 +model name : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz +stepping : 2 +microcode : 0x43 +cpu MHz : 2400.096 +cache size : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    -
    bash
    $  top -n 1
    +
    bash
    $  top -n 1
     
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
     
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
     
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
     
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 1 root 20 0 19696 2596 2268 S 0.0 0.3 0:01.21 init + 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd + 3 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    -
    sh
    $ sudo yum update -y
    -$ sudo yum install -y python36
    $ sudo yum update -y
    -$ sudo yum install -y python36
    +
    sh
    $ sudo yum update -y
    +$ sudo yum install -y python36
    $ sudo yum update -y
    +$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    -
    sh
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    +
    sh
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    -
    sh
    $ exit
    $ exit
    +
    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    @@ -27978,16 +27978,16 @@ import name

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    -
    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    +
    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    -
    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem
    +
    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    @@ -28019,7 +28019,7 @@ import name

    ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.

    -
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    +
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    @@ -28028,95 +28028,95 @@ import name

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する ( (#environments) を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    -
    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>
    +
    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    -
    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    +
    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    -
    python
    class MyFirstEc2(core.Stack):
    +
    python
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class MyFirstEc2(core.Stack):
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    + # + host = ec2.Instance( + self, "MyFirstEc2Instance", + instance_type=ec2.InstanceType("t2.micro"), + machine_image=ec2.MachineImage.latest_amazon_linux(), + vpc=vpc, + vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC), + security_group=sg, + key_name=key_name + )
    • まず最初に,VPC を定義する.

      @@ -28135,29 +28135,29 @@ import name

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    -
    python
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    +
    python
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

      @@ -28175,23 +28175,23 @@ import name

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    -
    python
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    +
    python
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    @@ -28261,23 +28261,23 @@ import name

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    -
    python
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    +
    python
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, (#sec_jupyter_and_deep_learning) でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    @@ -28285,13 +28285,13 @@ import name

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    -
    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started
    +
    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    -
    sh
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +
    sh
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は (#venv_quick_guide) に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    @@ -28301,21 +28301,21 @@ import name

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    -
    sh
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +
    sh
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    -
    sh
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +
    sh
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    -
    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"
    +
    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    -
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    +
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    @@ -28323,69 +28323,69 @@ import name

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    -
    sh
    $ cat /proc/cpuinfo
    +
    sh
    $ cat /proc/cpuinfo
     
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    $ cat /proc/cpuinfo
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB
    $ cat /proc/cpuinfo
     
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    +processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 63 +model name : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz +stepping : 2 +microcode : 0x43 +cpu MHz : 2400.096 +cache size : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    -
    bash
    $  top -n 1
    +
    bash
    $  top -n 1
     
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
     
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
     
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
     
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 1 root 20 0 19696 2596 2268 S 0.0 0.3 0:01.21 init + 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd + 3 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    -
    sh
    $ sudo yum update -y
    -$ sudo yum install -y python36
    $ sudo yum update -y
    -$ sudo yum install -y python36
    +
    sh
    $ sudo yum update -y
    +$ sudo yum install -y python36
    $ sudo yum update -y
    +$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    -
    sh
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    +
    sh
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    -
    sh
    $ exit
    $ exit
    +
    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    @@ -28399,16 +28399,16 @@ import name

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    -
    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    +
    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    -
    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem
    +
    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    @@ -28448,85 +28448,85 @@ import name

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    -
    python
    class Ec2ForDl(core.Stack):
    +
    python
    class Ec2ForDl(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class Ec2ForDl(core.Stack):
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class Ec2ForDl(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    + host = ec2.Instance( + self, "Ec2ForDl-Instance", + instance_type=ec2.InstanceType("g4dn.xlarge"), # + machine_image=ec2.MachineImage.generic_linux({ + "us-east-1": "ami-060f07284bb6f9faf", + "ap-northeast-1": "ami-09c0c16fc46a29ed9" + }), # + vpc=vpc, + vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC), + security_group=sg, + key_name=key_name + )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, (#sec_scientific_computing) ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

      @@ -28541,10 +28541,10 @@ import name

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    -
    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon
    +
    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    -
    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    +
    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    @@ -28553,43 +28553,43 @@ import name

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
     
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
     
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    +# デプロイを実行 +$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    -
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    +
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    @@ -28598,7 +28598,7 @@ import name

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    -
    sh
    $ nvidia-smi
    $ nvidia-smi
    +
    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    @@ -28606,14 +28606,14 @@ import name

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    -
    sh
    $ cd ~ # go to home directory
    -$ jupyter notebook
    $ cd ~ # go to home directory
    -$ jupyter notebook
    +
    sh
    $ cd ~ # go to home directory
    +$ jupyter notebook
    $ cd ~ # go to home directory
    +$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    -
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    +
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    @@ -28644,31 +28644,31 @@ import name

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    -
    python
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    +
    python
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    -
    python
    x = torch.rand(3,3)
    -print(x)
    x = torch.rand(3,3)
    -print(x)
    +
    python
    x = torch.rand(3,3)
    +print(x)
    x = torch.rand(3,3)
    +print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    -
    python
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    +
    python
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    -
    python
    z = x + y
    -print(z)
    z = x + y
    -print(z)
    +
    python
    z = x + y
    +print(z)
    z = x + y
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    -
    python
    z = z.to("cpu")
    -print(z)
    z = z.to("cpu")
    -print(z)
    +
    python
    z = z.to("cpu")
    +print(z)
    z = z.to("cpu")
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    @@ -28676,33 +28676,33 @@ import name

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    -
    python
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    +
    python
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
     
    -%time z = torch.matmul(x,y)
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    +%time z = torch.matmul(x,y)
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
     
    -%time z = torch.matmul(x,y)
    +%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    -
    python
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    +
    python
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
     
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
     
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    @@ -28717,140 +28717,140 @@ import name

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    -
    python
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    +
    python
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
     
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
     
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    +# custom functions and classes +from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    -
    python
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    +
    python
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
     
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
     
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
     
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
     
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf) +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    -
    python
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    +
    python
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
     
    -print("Example data size:", example_data.shape)
    +print("Example data size:", example_data.shape)
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
     
    -print("Example data size:", example_data.shape)
    +print("Example data size:", example_data.shape)
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    +fig = plt.figure(figsize=(10,4)) +for i in range(10): + plt.subplot(2,5,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], cmap='gray', interpolation='none') + plt.title("Ground Truth: {}".format(example_targets[i])) + plt.xticks([]) + plt.yticks([]) +plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    -
    python
    model = Model()
    -model.to("cuda") # load to GPU
    model = Model()
    -model.to("cuda") # load to GPU
    +
    python
    model = Model()
    +model.to("cuda") # load to GPU
    model = Model()
    +model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    -
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    +
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    -
    python
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +
    python
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
     
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
     
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    +plt.figure(figsize=(7,5)) +plt.plot(train_losses) +plt.xlabel("Iterations") +plt.ylabel("Train loss") +plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    -
    python
    model.eval()
    +
    python
    model.eval()
     
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    model.eval()
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    model.eval()
     
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    +fig = plt.figure(figsize=(10,4)) +for i in range(10): + plt.subplot(2,5,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], cmap='gray', interpolation='none') + plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item())) + plt.xticks([]) + plt.yticks([]) +plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    -
    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")
    +
    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は (#handson_01_delete_stack) 参照).

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    @@ -28880,85 +28880,85 @@ import name

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    -
    python
    class Ec2ForDl(core.Stack):
    +
    python
    class Ec2ForDl(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class Ec2ForDl(core.Stack):
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class Ec2ForDl(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    + host = ec2.Instance( + self, "Ec2ForDl-Instance", + instance_type=ec2.InstanceType("g4dn.xlarge"), # + machine_image=ec2.MachineImage.generic_linux({ + "us-east-1": "ami-060f07284bb6f9faf", + "ap-northeast-1": "ami-09c0c16fc46a29ed9" + }), # + vpc=vpc, + vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC), + security_group=sg, + key_name=key_name + )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, (#sec_scientific_computing) ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

      @@ -28973,10 +28973,10 @@ import name

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    -
    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon
    +
    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    -
    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    +
    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    @@ -28985,43 +28985,43 @@ import name

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
     
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
     
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    +# デプロイを実行 +$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    -
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    +
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    @@ -29030,7 +29030,7 @@ import name

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    -
    sh
    $ nvidia-smi
    $ nvidia-smi
    +
    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    @@ -29038,14 +29038,14 @@ import name

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    -
    sh
    $ cd ~ # go to home directory
    -$ jupyter notebook
    $ cd ~ # go to home directory
    -$ jupyter notebook
    +
    sh
    $ cd ~ # go to home directory
    +$ jupyter notebook
    $ cd ~ # go to home directory
    +$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している localhost:8888 には,ローカルマシンの localhost:8931 からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.

    -
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    +
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;
    http://localhost:8931/?token=XXXX&lt;/programlisting&gt;

    ?token=XXXX の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.

    上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (figure_title). これで, Jupyter の準備が整った!

    Jupyter ホーム画面

    @@ -29076,31 +29076,31 @@ import name

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    -
    python
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    +
    python
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    -
    python
    x = torch.rand(3,3)
    -print(x)
    x = torch.rand(3,3)
    -print(x)
    +
    python
    x = torch.rand(3,3)
    +print(x)
    x = torch.rand(3,3)
    +print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    -
    python
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    +
    python
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    -
    python
    z = x + y
    -print(z)
    z = x + y
    -print(z)
    +
    python
    z = x + y
    +print(z)
    z = x + y
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    -
    python
    z = z.to("cpu")
    -print(z)
    z = z.to("cpu")
    -print(z)
    +
    python
    z = z.to("cpu")
    +print(z)
    z = z.to("cpu")
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    @@ -29108,33 +29108,33 @@ import name

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    -
    python
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    +
    python
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
     
    -%time z = torch.matmul(x,y)
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    +%time z = torch.matmul(x,y)
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
     
    -%time z = torch.matmul(x,y)
    +%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    -
    python
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    +
    python
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
     
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
     
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    @@ -29149,140 +29149,140 @@ import name

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    -
    python
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    +
    python
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
     
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
     
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    +# custom functions and classes +from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    -
    python
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    +
    python
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
     
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
     
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
     
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
     
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf) +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    -
    python
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    +
    python
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
     
    -print("Example data size:", example_data.shape)
    +print("Example data size:", example_data.shape)
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
     
    -print("Example data size:", example_data.shape)
    +print("Example data size:", example_data.shape)
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    +fig = plt.figure(figsize=(10,4)) +for i in range(10): + plt.subplot(2,5,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], cmap='gray', interpolation='none') + plt.title("Ground Truth: {}".format(example_targets[i])) + plt.xticks([]) + plt.yticks([]) +plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    -
    python
    model = Model()
    -model.to("cuda") # load to GPU
    model = Model()
    -model.to("cuda") # load to GPU
    +
    python
    model = Model()
    +model.to("cuda") # load to GPU
    model = Model()
    +model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    -
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    +
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    -
    python
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +
    python
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
     
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
     
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    +plt.figure(figsize=(7,5)) +plt.plot(train_losses) +plt.xlabel("Iterations") +plt.ylabel("Train loss") +plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    -
    python
    model.eval()
    +
    python
    model.eval()
     
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    model.eval()
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    model.eval()
     
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    +fig = plt.figure(figsize=(10,4)) +for i in range(10): + plt.subplot(2,5,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], cmap='gray', interpolation='none') + plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item())) + plt.xticks([]) + plt.yticks([]) +plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    -
    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")
    +
    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は (#handson_01_delete_stack) 参照).

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    @@ -29310,11 +29310,11 @@ import name

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    -
    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    +
    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    answer: 1921
     
    @@ -29323,33 +29323,33 @@ import name

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    -
    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest
    +
    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    -
    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"
    +
    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    -
    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    +
    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    -
    json
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    +
    json
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    -
    sh
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    +
    sh
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    出力:

    -
    json
    {
    -    "score": 0.5235594527494207,
    -    "start": 470,
    -    "end": 506,
    -    "answer": "his services to theoretical physics,"
    -}
    {
    -    "score": 0.5235594527494207,
    -    "start": 470,
    -    "end": 506,
    -    "answer": "his services to theoretical physics,"
    -}
    +
    json
    {
    +    "score": 0.5235594527494207,
    +    "start": 470,
    +    "end": 506,
    +    "answer": "his services to theoretical physics,"
    +}
    {
    +    "score": 0.5235594527494207,
    +    "start": 470,
    +    "end": 506,
    +    "answer": "his services to theoretical physics,"
    +}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    @@ -29385,109 +29385,109 @@ import name

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    -
    python
    class EcsClusterQaBot(core.Stack):
    +
    python
    class EcsClusterQaBot(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
     
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
     
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
     
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
     
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    class EcsClusterQaBot(core.Stack):
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    class EcsClusterQaBot(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
     
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
     
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
     
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
     
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    + # + container = taskdef.add_container( + "EcsClusterQaBot-Container", + image=ecs.ContainerImage.from_registry( + "tomomano/qabot:latest" + ), + )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

      @@ -29507,39 +29507,39 @@ import name

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    -
    python
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    +
    python
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
     
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
     
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
     
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
     
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    +container = taskdef.add_container( + "EcsClusterQaBot-Container", + image=ecs.ContainerImage.from_registry( + "tomomano/qabot:latest" + ), +)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    @@ -29549,25 +29549,25 @@ import name

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    @@ -29579,7 +29579,7 @@ import name

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    -
    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    +
    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    @@ -29594,20 +29594,20 @@ import name

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    -
    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many
    +
    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    -
    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers
    +
    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    -
    sh
    $ python run_task.py clear
    $ python run_task.py clear
    +
    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy
    ]]> Hands-on #3: AWS で自動質問回答ボットを走らせる

    ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.

    @@ -29626,11 +29626,11 @@ import name

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    -
    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    +
    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    answer: 1921
     
    @@ -29639,33 +29639,33 @@ import name

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    -
    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest
    +
    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    -
    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"
    +
    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    -
    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    +
    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    -
    json
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    +
    json
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }
    { "score": 0.9881729286683587, "start": 437, "end": 441, "answer": "1921" }

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    -
    sh
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    +
    sh
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    出力:

    -
    json
    {
    -    "score": 0.5235594527494207,
    -    "start": 470,
    -    "end": 506,
    -    "answer": "his services to theoretical physics,"
    -}
    {
    -    "score": 0.5235594527494207,
    -    "start": 470,
    -    "end": 506,
    -    "answer": "his services to theoretical physics,"
    -}
    +
    json
    {
    +    "score": 0.5235594527494207,
    +    "start": 470,
    +    "end": 506,
    +    "answer": "his services to theoretical physics,"
    +}
    {
    +    "score": 0.5235594527494207,
    +    "start": 470,
    +    "end": 506,
    +    "answer": "his services to theoretical physics,"
    +}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    @@ -29701,109 +29701,109 @@ import name

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    -
    python
    class EcsClusterQaBot(core.Stack):
    +
    python
    class EcsClusterQaBot(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
     
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
     
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
     
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
     
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    class EcsClusterQaBot(core.Stack):
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    class EcsClusterQaBot(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
     
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
     
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
     
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
     
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    + # + container = taskdef.add_container( + "EcsClusterQaBot-Container", + image=ecs.ContainerImage.from_registry( + "tomomano/qabot:latest" + ), + )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

      @@ -29823,39 +29823,39 @@ import name

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    -
    python
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    +
    python
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
     
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
     
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
     
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
     
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    +container = taskdef.add_container( + "EcsClusterQaBot-Container", + image=ecs.ContainerImage.from_registry( + "tomomano/qabot:latest" + ), +)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    @@ -29865,25 +29865,25 @@ import name

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    @@ -29895,7 +29895,7 @@ import name

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    -
    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    +
    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    @@ -29910,20 +29910,20 @@ import name

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    -
    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many
    +
    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    -
    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers
    +
    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    -
    sh
    $ python run_task.py clear
    $ python run_task.py clear
    +
    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy
    ]]> @@ -29939,59 +29939,59 @@ import name

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    -
    python
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    +
    python
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
     
    -class SimpleLambda(core.Stack):
    +class SimpleLambda(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
     
    -class SimpleLambda(core.Stack):
    +class SimpleLambda(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    + # + handler = _lambda.Function( + self, 'LambdaHandler', + runtime=_lambda.Runtime.PYTHON_3_7, + code=_lambda.Code.from_inline(FUNC), + handler="index.handler", + memory_size=128, + timeout=core.Duration.seconds(10), + dead_letter_queue_enabled=True, + )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

      @@ -30023,25 +30023,25 @@ import name

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    @@ -30052,15 +30052,15 @@ import name

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    -
    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX
    +
    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    -
    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100
    +
    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    -
    sh
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    +
    sh
    ....................................................................................................
    +Submitted 100 tasks to Lambda!
    ....................................................................................................
    +Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    @@ -30070,44 +30070,44 @@ import name

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    -
    python
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +
    python
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    + table = ddb.Table( + self, "SimpleTable", + # + partition_key=ddb.Attribute( + name="item_id", + type=ddb.AttributeType.STRING + ), + # + billing_mode=ddb.BillingMode.PAY_PER_REQUEST, + # + removal_policy=core.RemovalPolicy.DESTROY + )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • @@ -30122,25 +30122,25 @@ import name

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    @@ -30150,167 +30150,167 @@ import name

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    -
    python
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    +
    python
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
     
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
     
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    +def write_item(table_name): + table = ddb.Table(table_name) + table.put_item( + Item={ + 'item_id': str(uuid4()), + 'first_name': 'John', + 'last_name': 'Doe', + 'age': 25, + } + )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    -
    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX
    +
    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    -
    python
    import boto3
    -ddb = boto3.resource('dynamodb')
    +
    python
    import boto3
    +ddb = boto3.resource('dynamodb')
     
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    import boto3
    -ddb = boto3.resource('dynamodb')
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)
    import boto3
    +ddb = boto3.resource('dynamodb')
     
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    +def scan_table(table_name): + table = ddb.Table(table_name) + items = table.scan().get("Items") + print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    -
    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX
    +
    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    -
    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000
    +
    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    -
    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2
    +
    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    -
    python
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +
    python
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    + # S3 bucket to store data + bucket = s3.Bucket( + self, "bucket", + removal_policy=core.RemovalPolicy.DESTROY, + auto_delete_objects=True, + )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    -
    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt
    +
    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    -
    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt
    +
    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    -
    python
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    +
    python
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if key is None:
    -        key = os.path.basename(filename)
    +    if key is None:
    +        key = os.path.basename(filename)
     
    -    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    +    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if key is None:
    -        key = os.path.basename(filename)
    +    if key is None:
    +        key = os.path.basename(filename)
     
    -    bucket.upload_file(filename, key)
    + bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    -
    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    +
    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    -
    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt
    +
    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    -
    python
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    +
    python
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if filename is None:
    -        filename = os.path.basename(key)
    +    if filename is None:
    +        filename = os.path.basename(key)
     
    -    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    +    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if filename is None:
    -        filename = os.path.basename(key)
    +    if filename is None:
    +        filename = os.path.basename(key)
     
    -    bucket.download_file(key, filename)
    + bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy
    ]]> Hands-on #5: サーバーレス入門

    前章ではサーバーレスアーキテクチャの概要の説明を行った. 本章では,ハンズオン形式でサーバーレスクラウドを実際に動かしながら,具体的な使用方法を学んでいこう. 今回のハンズオンでは Lambda, S3, DynamoDB の三つのサーバーレスクラウドの構成要素に触れていく. それぞれについて,短いチュートリアルを用意してある.

    @@ -30320,59 +30320,59 @@ import name

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    -
    python
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    +
    python
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
     
    -class SimpleLambda(core.Stack):
    +class SimpleLambda(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
     
    -class SimpleLambda(core.Stack):
    +class SimpleLambda(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    + # + handler = _lambda.Function( + self, 'LambdaHandler', + runtime=_lambda.Runtime.PYTHON_3_7, + code=_lambda.Code.from_inline(FUNC), + handler="index.handler", + memory_size=128, + timeout=core.Duration.seconds(10), + dead_letter_queue_enabled=True, + )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

      @@ -30404,25 +30404,25 @@ import name

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    @@ -30433,15 +30433,15 @@ import name

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    -
    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX
    +
    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    -
    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100
    +
    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    -
    sh
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    +
    sh
    ....................................................................................................
    +Submitted 100 tasks to Lambda!
    ....................................................................................................
    +Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    @@ -30451,44 +30451,44 @@ import name

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    -
    python
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +
    python
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    + table = ddb.Table( + self, "SimpleTable", + # + partition_key=ddb.Attribute( + name="item_id", + type=ddb.AttributeType.STRING + ), + # + billing_mode=ddb.BillingMode.PAY_PER_REQUEST, + # + removal_policy=core.RemovalPolicy.DESTROY + )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • @@ -30503,25 +30503,25 @@ import name

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    @@ -30531,167 +30531,167 @@ import name

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    -
    python
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    +
    python
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
     
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
     
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    +def write_item(table_name): + table = ddb.Table(table_name) + table.put_item( + Item={ + 'item_id': str(uuid4()), + 'first_name': 'John', + 'last_name': 'Doe', + 'age': 25, + } + )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    -
    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX
    +
    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    -
    python
    import boto3
    -ddb = boto3.resource('dynamodb')
    +
    python
    import boto3
    +ddb = boto3.resource('dynamodb')
     
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    import boto3
    -ddb = boto3.resource('dynamodb')
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)
    import boto3
    +ddb = boto3.resource('dynamodb')
     
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    +def scan_table(table_name): + table = ddb.Table(table_name) + items = table.scan().get("Items") + print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    -
    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX
    +
    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    -
    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000
    +
    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    -
    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2
    +
    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    -
    python
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +
    python
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    + # S3 bucket to store data + bucket = s3.Bucket( + self, "bucket", + removal_policy=core.RemovalPolicy.DESTROY, + auto_delete_objects=True, + )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに ( (#aws_cli_install)).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    -
    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt
    +
    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    -
    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt
    +
    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    -
    python
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    +
    python
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if key is None:
    -        key = os.path.basename(filename)
    +    if key is None:
    +        key = os.path.basename(filename)
     
    -    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    +    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if key is None:
    -        key = os.path.basename(filename)
    +    if key is None:
    +        key = os.path.basename(filename)
     
    -    bucket.upload_file(filename, key)
    + bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    -
    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    +
    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    -
    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt
    +
    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    -
    python
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    +
    python
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if filename is None:
    -        filename = os.path.basename(key)
    +    if filename is None:
    +        filename = os.path.basename(key)
     
    -    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    +    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if filename is None:
    -        filename = os.path.basename(key)
    +    if filename is None:
    +        filename = os.path.basename(key)
     
    -    bucket.download_file(key, filename)
    + bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy
    ]]> @@ -30750,7 +30750,7 @@ import name

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    -
    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc
    +
    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は (#sec_handson_docker) に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    @@ -30830,7 +30830,7 @@ import name

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    -
    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc
    +
    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は (#sec_handson_docker) に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    @@ -30932,7 +30932,7 @@ import name

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    -
    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc
    +
    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は ハンズオン実行用の Docker image の使い方 に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    @@ -31099,44 +31099,44 @@ import name

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    -
    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    +
    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    -
    python
    import boto3
    +
    python
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    +s3_client = boto3.client("s3", region_name="ap-northeast-1") +s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    -
    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    +
    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン (Hands-on #1: 初めての EC2 インスタンスを起動する) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    -
    python
    import boto3
    +
    python
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    import boto3
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    +ec2_client = boto3.client("ec2") +ec2_client.run_instances( + ImageId="ami-xxxxxxxxx", + MinCount=1, + MaxCount=1, + KeyName="MyKeyPair", + InstanceType="t2.micro", + SecurityGroupIds=["sg-903004f8"], + SubnetId="subnet-6e7f829e", +)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    @@ -31144,34 +31144,34 @@ import name

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは AWS CLI のインストール を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    -
    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    +
    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    -
    sh
    $ aws s3 ls
    +
    sh
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    -
    sh
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    +
    sh
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    -
    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +
    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    +2020-06-07 23:54:19 13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    -
    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force
    +
    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    @@ -31187,120 +31187,120 @@ import name

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    -
    json
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +
    json
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    + "/opt/aws/bin/cfn-signal -e $? ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WebServer ", + " --region ", { "Ref" : "AWS::Region" }, "\n" + ]]}} + }, + ... + }, + ... +},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    -
    python
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +
    python
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    + host = ec2.Instance( + self, "MyGreatEc2", + instance_type=ec2.InstanceType("t2.micro"), + machine_image=ec2.MachineImage.latest_amazon_linux(), + vpc=vpc, + ... + )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

      @@ -31319,7 +31319,7 @@ import name
  • AWS CDK: AWS CDK のインストールについては, AWS CDK のインストール を参照.
  • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.
  • -
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    +
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    @@ -31328,95 +31328,95 @@ import name

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する (環境構築 を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    -
    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>
    +
    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    -
    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    +
    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    -
    python
    class MyFirstEc2(core.Stack):
    +
    python
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class MyFirstEc2(core.Stack):
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    + # + host = ec2.Instance( + self, "MyFirstEc2Instance", + instance_type=ec2.InstanceType("t2.micro"), + machine_image=ec2.MachineImage.latest_amazon_linux(), + vpc=vpc, + vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC), + security_group=sg, + key_name=key_name + )
    • まず最初に,VPC を定義する.

      @@ -31435,29 +31435,29 @@ import name

    VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

    本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

    興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

    -
    python
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    vpc = ec2.Vpc(
    -    self, "MyFirstEc2-Vpc",
    -    max_azs=1,
    -    cidr="10.10.0.0/23",
    -    subnet_configuration=[
    -        ec2.SubnetConfiguration(
    -            name="public",
    -            subnet_type=ec2.SubnetType.PUBLIC,
    -        )
    -    ],
    -    nat_gateways=0,
    -)
    +
    python
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    vpc = ec2.Vpc(
    +    self, "MyFirstEc2-Vpc",
    +    max_azs=1,
    +    cidr="10.10.0.0/23",
    +    subnet_configuration=[
    +        ec2.SubnetConfiguration(
    +            name="public",
    +            subnet_type=ec2.SubnetType.PUBLIC,
    +        )
    +    ],
    +    nat_gateways=0,
    +)
    • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

      @@ -31475,23 +31475,23 @@ import name

    Security Group

    Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

    コードの該当部分を見てみよう.

    -
    python
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    sg = ec2.SecurityGroup(
    -    self, "MyFirstEc2Vpc-Sg",
    -    vpc=vpc,
    -    allow_all_outbound=True,
    -)
    -sg.add_ingress_rule(
    -    peer=ec2.Peer.any_ipv4(),
    -    connection=ec2.Port.tcp(22),
    -)
    +
    python
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)
    sg = ec2.SecurityGroup(
    +    self, "MyFirstEc2Vpc-Sg",
    +    vpc=vpc,
    +    allow_all_outbound=True,
    +)
    +sg.add_ingress_rule(
    +    peer=ec2.Peer.any_ipv4(),
    +    connection=ec2.Port.tcp(22),
    +)

    本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

    SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

    セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

    @@ -31506,23 +31506,23 @@ import name

    table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

    上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

    EC2 インスタンスを定義しているコードの該当部分を見てみよう.

    -
    python
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    host = ec2.Instance(
    -    self, "MyFirstEc2Instance",
    -    instance_type=ec2.InstanceType("t2.micro"),
    -    machine_image=ec2.MachineImage.latest_amazon_linux(),
    -    vpc=vpc,
    -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -    security_group=sg,
    -    key_name=key_name
    -)
    +
    python
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)
    host = ec2.Instance(
    +    self, "MyFirstEc2Instance",
    +    instance_type=ec2.InstanceType("t2.micro"),
    +    machine_image=ec2.MachineImage.latest_amazon_linux(),
    +    vpc=vpc,
    +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +    security_group=sg,
    +    key_name=key_name
    +)

    ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, Hands-on #2: AWS でディープラーニングを実践 でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

    以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

    プログラムを実行する

    @@ -31530,13 +31530,13 @@ import name

    Python の依存ライブラリのインストール

    まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

    まずは, handson/ec2-get-started のディレクトリに移動しよう.

    -
    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started
    +
    sh
    $ cd handson/ec2-get-started
    $ cd handson/ec2-get-started

    ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

    -
    sh
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    $ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +
    sh
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
    $ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt

    これで Python の環境構築は完了だ.

    venv の簡単な説明は Python クイックガイド に記述してある.

    環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

    @@ -31546,21 +31546,21 @@ import name

    SSH 鍵を生成

    EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

    次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

    -
    sh
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +
    sh
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    $ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem

    このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

    -
    sh
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +
    sh
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
    $ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem

    デプロイを実行

    これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

    -
    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"
    +
    sh
    $ cdk deploy -c key_name="HirakeGoma"
    $ cdk deploy -c key_name="HirakeGoma"

    このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

    CDKデプロイ実行後の出力

    SSH でログイン

    早速,SSH  で接続してみよう.

    -
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    +
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

    -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

    ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

    SSH で EC2 インスタンスにログイン

    @@ -31568,69 +31568,69 @@ import name

    起動した EC2 インスタンスで遊んでみる

    せっかく新しいインスタンスを起動したので,少し遊んでみよう.

    ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

    -
    sh
    $ cat /proc/cpuinfo
    +
    sh
    $ cat /proc/cpuinfo
     
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    $ cat /proc/cpuinfo
    +processor       : 0
    +vendor_id       : GenuineIntel
    +cpu family      : 6
    +model           : 63
    +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    +stepping        : 2
    +microcode       : 0x43
    +cpu MHz         : 2400.096
    +cache size      : 30720 KB
    $ cat /proc/cpuinfo
     
    -processor       : 0
    -vendor_id       : GenuineIntel
    -cpu family      : 6
    -model           : 63
    -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
    -stepping        : 2
    -microcode       : 0x43
    -cpu MHz         : 2400.096
    -cache size      : 30720 KB
    +processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 63 +model name : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz +stepping : 2 +microcode : 0x43 +cpu MHz : 2400.096 +cache size : 30720 KB

    次に,実行中のプロセスやメモリの消費を見てみよう.

    -
    sh
    $  top -n 1
    +
    sh
    $  top -n 1
     
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
     
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
    +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    $  top -n 1
     
    -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    -Swap:        0k total,        0k used,        0k free,   185856k cached
    +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
    +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
    +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
    +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
    +Swap:        0k total,        0k used,        0k free,   185856k cached
     
    -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
    -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
    + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 1 root 20 0 19696 2596 2268 S 0.0 0.3 0:01.21 init + 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd + 3 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0

    t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

    今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

    -
    sh
    $ sudo yum update -y
    -$ sudo yum install -y python36
    $ sudo yum update -y
    -$ sudo yum install -y python36
    +
    sh
    $ sudo yum update -y
    +$ sudo yum install -y python36
    $ sudo yum update -y
    +$ sudo yum install -y python36

    インストールした Python を起動してみよう.

    -
    sh
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    $ python3
    -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>>
    +
    sh
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>
    $ python3
    +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
    +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>>

    Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

    さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

    -
    sh
    $ exit
    $ exit
    +
    sh
    $ exit
    $ exit

    AWS コンソールから確認

    これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

    まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

    @@ -31644,16 +31644,16 @@ import name

    一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

    CloudFormationコンソール画面から,スタックを削除

    二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

    スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

    また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

    コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

    EC2でSSH鍵ペアを削除

    コマンドラインから実行するには,次のコマンドを使う.

    -
    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    +
    sh
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"
    $ aws ec2 delete-key-pair --key-name "HirakeGoma"

    最後に,ローカルのコンピュータから鍵を削除する.

    -
    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem
    +
    sh
    $ rm -f ~/.ssh/HirakeGoma.pem
    $ rm -f ~/.ssh/HirakeGoma.pem

    これで,クラウドの片付けもすべて終了だ.

    なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

    小括

    @@ -31722,85 +31722,85 @@ import name

    ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

    -
    python
    class Ec2ForDl(core.Stack):
    +
    python
    class Ec2ForDl(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class Ec2ForDl(core.Stack):
    +        host = ec2.Instance(
    +            self, "Ec2ForDl-Instance",
    +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    +            machine_image=ec2.MachineImage.generic_linux({
    +                "us-east-1": "ami-060f07284bb6f9faf",
    +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    +            }), #
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class Ec2ForDl(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            self, "Ec2ForDl-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        vpc = ec2.Vpc(
    +            self, "Ec2ForDl-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            self, "Ec2ForDl-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        sg = ec2.SecurityGroup(
    +            self, "Ec2ForDl-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        host = ec2.Instance(
    -            self, "Ec2ForDl-Instance",
    -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
    -            machine_image=ec2.MachineImage.generic_linux({
    -                "us-east-1": "ami-060f07284bb6f9faf",
    -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
    -            }), #
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    + host = ec2.Instance( + self, "Ec2ForDl-Instance", + instance_type=ec2.InstanceType("g4dn.xlarge"), # + machine_image=ec2.MachineImage.generic_linux({ + "us-east-1": "ami-060f07284bb6f9faf", + "ap-northeast-1": "ami-09c0c16fc46a29ed9" + }), # + vpc=vpc, + vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC), + security_group=sg, + key_name=key_name + )
    • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, クラウドで行う科学計算・機械学習 ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

      @@ -31815,10 +31815,10 @@ import name

    AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

    しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

    AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

    -
    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon
    +
    sh
    $ aws ec2 describe-images --owners amazon
    $ aws ec2 describe-images --owners amazon

    ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

    本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

    -
    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    +
    sh
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
    $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

    AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

    figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

    DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

    @@ -31827,43 +31827,43 @@ import name

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
     
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    -$ cd handson/mnist
    +# デプロイを実行
    +$ cdk deploy -c key_name="HirakeGoma"
    # プロジェクトのディレクトリに移動
    +$ cd handson/mnist
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# SSH鍵を生成
    -$ export KEY_NAME="HirakeGoma"
    -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    -$ mv HirakeGoma.pem ~/.ssh/
    -$ chmod 400 ~/.ssh/HirakeGoma.pem
    +# SSH鍵を生成
    +$ export KEY_NAME="HirakeGoma"
    +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
    +$ mv HirakeGoma.pem ~/.ssh/
    +$ chmod 400 ~/.ssh/HirakeGoma.pem
     
    -# デプロイを実行
    -$ cdk deploy -c key_name="HirakeGoma"
    +# デプロイを実行 +$ cdk deploy -c key_name="HirakeGoma"

    ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

    CDKデプロイ実行後の出力

    ログイン

    早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

    -
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    +
    sh
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
    $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

    ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

    SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

    ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

    @@ -31872,7 +31872,7 @@ import name

    SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

    その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

    SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

    -
    sh
    $ nvidia-smi
    $ nvidia-smi
    +
    sh
    $ nvidia-smi
    $ nvidia-smi

    figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

    nvidia-smi の出力

    Jupyter Notebook の起動

    @@ -31880,9 +31880,9 @@ import name

    Jupyter Notebook の画面

    このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

    早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

    -
    sh
    $ cd ~ # go to home directory
    -$ jupyter notebook
    $ cd ~ # go to home directory
    -$ jupyter notebook
    +
    sh
    $ cd ~ # go to home directory
    +$ jupyter notebook
    $ cd ~ # go to home directory
    +$ jupyter notebook

    このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

    Jupyter Notebook サーバーを起動

    Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

    @@ -31918,31 +31918,31 @@ import name

    ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

    PyTorch始めの一歩

    まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

    -
    python
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    -print("Is CUDA ready?", torch.cuda.is_available())
    +
    python
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())
    import torch
    +print("Is CUDA ready?", torch.cuda.is_available())

    出力:

    Is CUDA ready? True</programlisting>

    次に,3x3 のランダムな行列を CPU 上に作ってみよう.

    -
    python
    x = torch.rand(3,3)
    -print(x)
    x = torch.rand(3,3)
    -print(x)
    +
    python
    x = torch.rand(3,3)
    +print(x)
    x = torch.rand(3,3)
    +print(x)

    出力:

    tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

    次に,行列を GPU 上に作成する.

    -
    python
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    -x = x.to("cuda")
    +
    python
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")
    y = torch.ones_like(x, device="cuda")
    +x = x.to("cuda")

    そして,行列 xy の加算を,GPU 上で実行する

    -
    python
    z = x + y
    -print(z)
    z = x + y
    -print(z)
    +
    python
    z = x + y
    +print(z)
    z = x + y
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

    最後に, GPU 上にある行列を, CPU に戻す.

    -
    python
    z = z.to("cpu")
    -print(z)
    z = z.to("cpu")
    -print(z)
    +
    python
    z = z.to("cpu")
    +print(z)
    z = z.to("cpu")
    +print(z)

    出力:

    tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

    以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

    @@ -31950,33 +31950,33 @@ import name

    しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

    実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

    まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

    -
    python
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    +
    python
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
     
    -%time z = torch.matmul(x,y)
    s = 10000
    -device = "cpu"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    +%time z = torch.matmul(x,y)
    s = 10000
    +device = "cpu"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
     
    -%time z = torch.matmul(x,y)
    +%time z = torch.matmul(x,y)

    出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

    CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

    次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

    -
    python
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    +
    python
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
     
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    -device = "cuda"
    -x = torch.rand(s, s, device=device, dtype=torch.float32)
    -y = torch.rand(s, s, device=device, dtype=torch.float32)
    -torch.cuda.synchronize()
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()
    s = 10000
    +device = "cuda"
    +x = torch.rand(s, s, device=device, dtype=torch.float32)
    +y = torch.rand(s, s, device=device, dtype=torch.float32)
    +torch.cuda.synchronize()
     
    -%time z = torch.matmul(x,y); torch.cuda.synchronize()
    +%time z = torch.matmul(x,y); torch.cuda.synchronize()

    出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

    CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

    PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

    @@ -31991,140 +31991,140 @@ import name

     をアップロード

    simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

    新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

    -
    python
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    +
    python
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
     
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    import torch
    -import torch.optim as optim
    -import torchvision
    -from torchvision import datasets, transforms
    -from matplotlib import pyplot as plt
    +# custom functions and classes
    +from simple_mnist import Model, train, evaluate
    import torch
    +import torch.optim as optim
    +import torchvision
    +from torchvision import datasets, transforms
    +from matplotlib import pyplot as plt
     
    -# custom functions and classes
    -from simple_mnist import Model, train, evaluate
    +# custom functions and classes +from simple_mnist import Model, train, evaluate

    torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

    次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

    -
    python
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    +
    python
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
     
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
     
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    -                             transforms.Normalize((0.1307,), (0.3081,))])
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    transf = transforms.Compose([transforms.ToTensor(),
    +                             transforms.Normalize((0.1307,), (0.3081,))])
     
    -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
    +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
    +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
     
    -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
    -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
    +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf) +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

    今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

    -
    python
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    +
    python
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
     
    -print("Example data size:", example_data.shape)
    +print("Example data size:", example_data.shape)
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    examples = iter(testloader)
    -example_data, example_targets = examples.next()
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Ground Truth: {}".format(example_targets[i]))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    examples = iter(testloader)
    +example_data, example_targets = examples.next()
     
    -print("Example data size:", example_data.shape)
    +print("Example data size:", example_data.shape)
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Ground Truth: {}".format(example_targets[i]))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    +fig = plt.figure(figsize=(10,4)) +for i in range(10): + plt.subplot(2,5,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], cmap='gray', interpolation='none') + plt.title("Ground Truth: {}".format(example_targets[i])) + plt.xticks([]) + plt.yticks([]) +plt.show()

    MNIST の手書き数字画像とその教師ラベル

    次に, CNN のモデルを定義する.

    -
    python
    model = Model()
    -model.to("cuda") # load to GPU
    model = Model()
    -model.to("cuda") # load to GPU
    +
    python
    model = Model()
    +model.to("cuda") # load to GPU
    model = Model()
    +model.to("cuda") # load to GPU

    今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

    本ハンズオンで使用するニューラルネットの構造.

    続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

    -
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    +
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    これで,準備が整った. CNN の学習ループを開始しよう!

    -
    python
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +
    python
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
     
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    train_losses = []
    -for epoch in range(5):
    -    losses = train(model, trainloader, optimizer, epoch)
    -    train_losses = train_losses + losses
    -    test_loss, test_accuracy = evaluate(model, testloader)
    -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
    +plt.figure(figsize=(7,5))
    +plt.plot(train_losses)
    +plt.xlabel("Iterations")
    +plt.ylabel("Train loss")
    +plt.show()
    train_losses = []
    +for epoch in range(5):
    +    losses = train(model, trainloader, optimizer, epoch)
    +    train_losses = train_losses + losses
    +    test_loss, test_accuracy = evaluate(model, testloader)
    +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
     
    -plt.figure(figsize=(7,5))
    -plt.plot(train_losses)
    -plt.xlabel("Iterations")
    -plt.ylabel("Train loss")
    -plt.show()
    +plt.figure(figsize=(7,5)) +plt.plot(train_losses) +plt.xlabel("Iterations") +plt.ylabel("Train loss") +plt.show()

    ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

    出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

    学習の進行に対する Train loss の変化

    出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

    学習したCNNのテストデータに対するスコア (5エポック後)

    学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

    -
    python
    model.eval()
    +
    python
    model.eval()
     
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    model.eval()
    +fig = plt.figure(figsize=(10,4))
    +for i in range(10):
    +    plt.subplot(2,5,i+1)
    +    plt.tight_layout()
    +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    +    plt.xticks([])
    +    plt.yticks([])
    +plt.show()
    model.eval()
     
    -with torch.no_grad():
    -    output = model(example_data.to("cuda"))
    +with torch.no_grad():
    +    output = model(example_data.to("cuda"))
     
    -fig = plt.figure(figsize=(10,4))
    -for i in range(10):
    -    plt.subplot(2,5,i+1)
    -    plt.tight_layout()
    -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    -    plt.xticks([])
    -    plt.yticks([])
    -plt.show()
    +fig = plt.figure(figsize=(10,4)) +for i in range(10): + plt.subplot(2,5,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], cmap='gray', interpolation='none') + plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item())) + plt.xticks([]) + plt.yticks([]) +plt.show()

    学習した CNN による,MNIST画像の推論結果

    最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

    -
    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")
    +
    python
    torch.save(model.state_dict(), "mnist_cnn.pt")
    torch.save(model.state_dict(), "mnist_cnn.pt")

    以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

    スタックの削除

    これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

    ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は スタックを削除 参照).

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

    AWS のバジェットアラート

    AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

    @@ -32163,92 +32163,92 @@ import name

    イメージをダウンロード

    パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

    たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

    -
    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04
    +
    sh
    $ docker pull ubuntu:18.04
    $ docker pull ubuntu:18.04

    ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

    pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

    コンテナを起動

    Pull してきたイメージを起動するには, run コマンドを使う.

    -
    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04
    +
    sh
    $ docker run -it ubuntu:18.04
    $ docker run -it ubuntu:18.04

    ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

    このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

    Docker を使って ubuntu:18.04 イメージを起動

    ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, Hands-on #2: AWS でディープラーニングを実践 でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

    これを起動してみよう.

    -
    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch
    +
    sh
    $ docker run -it pytorch/pytorch
    $ docker run -it pytorch/pytorch

    docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

    pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

    -
    sh
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    $ python3
    -Python 3.7.7 (default, May  7 2020, 21:25:33)
    -[GCC 7.3.0] :: Anaconda, Inc. on linux
    -Type "help", "copyright", "credits" or "license" for more information.
    ->>> import torch
    ->>> torch.cuda.is_available()
    -False
    +
    sh
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False
    $ python3
    +Python 3.7.7 (default, May  7 2020, 21:25:33)
    +[GCC 7.3.0] :: Anaconda, Inc. on linux
    +Type "help", "copyright", "credits" or "license" for more information.
    +>>> import torch
    +>>> torch.cuda.is_available()
    +False

    このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

    自分だけのイメージを作る

    自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

    たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

    カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

    具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

    -
    python
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +
    python
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \
    -    && apt-get install nano
    +RUN apt-get update \
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
     
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    FROM node:12
    -LABEL maintainer="Tomoyuki Mano"
    +# copy hands-on source code in /root/
    +COPY handson/ /root/handson
    FROM node:12
    +LABEL maintainer="Tomoyuki Mano"
     
    -RUN apt-get update \
    -    && apt-get install nano
    +RUN apt-get update \
    +    && apt-get install nano
     
    -#
    -RUN cd /opt \
    -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    -    && tar -xzf Python-3.7.6.tgz \
    -    && cd Python-3.7.6 \
    -    && ./configure --enable-optimizations \
    -    && make install
    +#
    +RUN cd /opt \
    +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
    +    && tar -xzf Python-3.7.6.tgz \
    +    && cd Python-3.7.6 \
    +    && ./configure --enable-optimizations \
    +    && make install
     
    -RUN cd /opt \
    -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    -    && unzip awscliv2.zip \
    -    && ./aws/install
    +RUN cd /opt \
    +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    +    && unzip awscliv2.zip \
    +    && ./aws/install
     
    -#
    -RUN npm install -g aws-cdk@1.100
    +#
    +RUN npm install -g aws-cdk@1.100
     
    -# clean up unnecessary files
    -RUN rm -rf /opt/*
    +# clean up unnecessary files
    +RUN rm -rf /opt/*
     
    -# copy hands-on source code in /root/
    -COPY handson/ /root/handson
    +# copy hands-on source code in /root/ +COPY handson/ /root/handson

    Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

    "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

    コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

    @@ -32282,35 +32282,35 @@ import name

    このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

    Transformer を用いた question-answering プログラム

    このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

    -
    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    -
    -question: In what year did Einstein win the Nobel prize?
    +
    txt
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?
    context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
    +
    +question: In what year did Einstein win the Nobel prize?

    今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

    -
    sh
    answer: 1921
    answer: 1921
    +
    sh
    answer: 1921
    answer: 1921

    人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

    今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

    Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

    なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

    次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

    -
    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest
    +
    sh
    $ docker pull tomomano/qabot:latest
    $ docker pull tomomano/qabot:latest

    pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

    -
    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    -$ question="In what year did Einstein win the Nobel prize ?"
    +
    sh
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"
    $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
    +$ question="In what year did Einstein win the Nobel prize ?"

    そうしたら,次のコマンドによってコンテナを実行する.

    -
    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    +
    sh
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

    このコマンドを実行すると,次のような出力が得られるはずである.

    -
    sh
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
    +
    sh
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
    {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}

    "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

    もう少し難しい質問を投げかけてみよう.

    -
    sh
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    +
    sh
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
    $ question="Why did Einstein win the Nobel prize ?"
    +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

    出力:

    -
    sh
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
    +
    sh
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
    {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}

    今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

    このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

    今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

    @@ -32346,109 +32346,109 @@ import name

    それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

    -
    sh
    class EcsClusterQaBot(core.Stack):
    +
    sh
    class EcsClusterQaBot(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
     
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
     
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
     
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
     
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    class EcsClusterQaBot(core.Stack):
    +        #
    +        container = taskdef.add_container(
    +            "EcsClusterQaBot-Container",
    +            image=ecs.ContainerImage.from_registry(
    +                "tomomano/qabot:latest"
    +            ),
    +        )
    class EcsClusterQaBot(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store questions and answers
    -        table = dynamodb.Table(
    -            self, "EcsClusterQaBot-Table",
    -            partition_key=dynamodb.Attribute(
    -                name="item_id", type=dynamodb.AttributeType.STRING
    -            ),
    -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store questions and answers
    +        table = dynamodb.Table(
    +            self, "EcsClusterQaBot-Table",
    +            partition_key=dynamodb.Attribute(
    +                name="item_id", type=dynamodb.AttributeType.STRING
    +            ),
    +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "EcsClusterQaBot-Vpc",
    -            max_azs=1,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "EcsClusterQaBot-Vpc",
    +            max_azs=1,
    +        )
     
    -        #
    -        cluster = ecs.Cluster(
    -            self, "EcsClusterQaBot-Cluster",
    -            vpc=vpc,
    -        )
    +        #
    +        cluster = ecs.Cluster(
    +            self, "EcsClusterQaBot-Cluster",
    +            vpc=vpc,
    +        )
     
    -        #
    -        taskdef = ecs.FargateTaskDefinition(
    -            self, "EcsClusterQaBot-TaskDef",
    -            cpu=1024, # 1 CPU
    -            memory_limit_mib=4096, # 4GB RAM
    -        )
    +        #
    +        taskdef = ecs.FargateTaskDefinition(
    +            self, "EcsClusterQaBot-TaskDef",
    +            cpu=1024, # 1 CPU
    +            memory_limit_mib=4096, # 4GB RAM
    +        )
     
    -        # grant permissions
    -        table.grant_read_write_data(taskdef.task_role)
    -        taskdef.add_to_task_role_policy(
    -            iam.PolicyStatement(
    -                effect=iam.Effect.ALLOW,
    -                resources=["*"],
    -                actions=["ssm:GetParameter"]
    -            )
    -        )
    +        # grant permissions
    +        table.grant_read_write_data(taskdef.task_role)
    +        taskdef.add_to_task_role_policy(
    +            iam.PolicyStatement(
    +                effect=iam.Effect.ALLOW,
    +                resources=["*"],
    +                actions=["ssm:GetParameter"]
    +            )
    +        )
     
    -        #
    -        container = taskdef.add_container(
    -            "EcsClusterQaBot-Container",
    -            image=ecs.ContainerImage.from_registry(
    -                "tomomano/qabot:latest"
    -            ),
    -        )
    + # + container = taskdef.add_container( + "EcsClusterQaBot-Container", + image=ecs.ContainerImage.from_registry( + "tomomano/qabot:latest" + ), + )
    • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

      @@ -32468,39 +32468,39 @@ import name

    ECS と Fargate

    ECS と Fargate の部分について,コードをくわしく見てみよう.

    -
    sh
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    +
    sh
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
     
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
     
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    cluster = ecs.Cluster(
    -    self, "EcsClusterQaBot-Cluster",
    -    vpc=vpc,
    -)
    +container = taskdef.add_container(
    +    "EcsClusterQaBot-Container",
    +    image=ecs.ContainerImage.from_registry(
    +        "tomomano/qabot:latest"
    +    ),
    +)
    cluster = ecs.Cluster(
    +    self, "EcsClusterQaBot-Cluster",
    +    vpc=vpc,
    +)
     
    -taskdef = ecs.FargateTaskDefinition(
    -    self, "EcsClusterQaBot-TaskDef",
    -    cpu=1024, # 1 CPU
    -    memory_limit_mib=4096, # 4GB RAM
    -)
    +taskdef = ecs.FargateTaskDefinition(
    +    self, "EcsClusterQaBot-TaskDef",
    +    cpu=1024, # 1 CPU
    +    memory_limit_mib=4096, # 4GB RAM
    +)
     
    -container = taskdef.add_container(
    -    "EcsClusterQaBot-Container",
    -    image=ecs.ContainerImage.from_registry(
    -        "tomomano/qabot:latest"
    -    ),
    -)
    +container = taskdef.add_container( + "EcsClusterQaBot-Container", + image=ecs.ContainerImage.from_registry( + "tomomano/qabot:latest" + ), +)

    cluster = の箇所で,空の ECS クラスターを定義している.

    次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

    最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

    @@ -32510,25 +32510,25 @@ import name

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/qa-bot
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/qa-bot
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

    @@ -32540,7 +32540,7 @@ import name

    それでは,質問をデプロイしたクラウドに提出してみよう.

    ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

    次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

    -
    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    +
    sh
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
    $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

    run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

    "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

    このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

    @@ -32555,20 +32555,20 @@ import name

    タスクの同時実行

    さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

    次のようなコマンドを実行しよう.

    -
    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many
    +
    sh
    $ python run_task.py ask_many
    $ python run_task.py ask_many

    このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

    複数の質問タスクを同時に投入する

    すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

    -
    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers
    +
    sh
    $ python run_task.py list_answers
    $ python run_task.py list_answers

    結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

     の実行結果

    おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

    run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

    -
    sh
    $ python run_task.py clear
    $ python run_task.py clear
    +
    sh
    $ python run_task.py clear
    $ python run_task.py clear

    スタックの削除

    これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

    スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する

    ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

    本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

    @@ -32597,7 +32597,7 @@ import name

    準備 でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

    MNIST 手書き文字認識 (再訪)

    今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, 実践ディープラーニング! MNIST 手書き数字認識タスク で扱った MNIST 手書き文字認識の問題を再度取り上げよう. 実践ディープラーニング! MNIST 手書き数字認識タスク では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

    -
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    +
    python
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

    機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

    グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

    @@ -32608,18 +32608,18 @@ import name

    まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

    Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に 実践ディープラーニング! MNIST 手書き数字認識タスク のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

    練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

    -
    sh
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    -$ docker build -t mymnist .
    +
    sh
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .
    $ cd handson/aws-batch/docker
    +$ docker build -t mymnist .

    docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

    手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

    -
    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest
    +
    sh
    $ docker pull tomomano/mymnist:latest
    $ docker pull tomomano/mymnist:latest

    イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

    -
    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    +
    sh
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. Hands-on #2: AWS でディープラーニングを実践 のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

    Docker を実行した際の出力

    上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

    -
    sh
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    +
    sh
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10

    このコマンドでは,--gpus all というパラメータが加わった.

    CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

    (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

    @@ -32653,163 +32653,163 @@ import name

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    -
    python
    class SimpleBatch(core.Stack):
    +
    python
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    class SimpleBatch(core.Stack):
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    + # + job_def = batch.JobDefinition( + self, "job-definition", + container=batch.JobDefinitionContainer( + image=ecs.ContainerImage.from_ecr_repository(repo), + command=["python3", "main.py"], + vcpus=4, + gpu_count=1, + memory_limit_mib=12000, + job_role=job_role, + environment={ + "BUCKET_NAME": bucket.bucket_name + } + ), + job_definition_name=self.stack_name + "job-definition", + timeout=core.Duration.hours(2), + )
    • で,計算結果を保存するための S3 バケットを用意している

      @@ -32836,25 +32836,25 @@ import name

    スタックのデプロイ

    スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/aws-batch
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/aws-batch
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

    AWS Batch のコンソール画面 (ダッシュボード)

    まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

    @@ -32864,33 +32864,33 @@ import name

    Docker image を ECR に配置する

    さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン (Hands-on #3: AWS で自動質問回答ボットを走らせる) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

    スタックのソースコードでいうと,次の箇所が ECR を定義している.

    -
    python
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    +
    python
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
     
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    #
    -repo = ecr.Repository(
    -    self, "repository",
    -    removal_policy=core.RemovalPolicy.DESTROY,
    -)
    +job_def = batch.JobDefinition(
    +    self, "job-definition",
    +    container=batch.JobDefinitionContainer(
    +        image=ecs.ContainerImage.from_ecr_repository(repo), #
    +        ...
    +    ),
    +    ...
    +)
    #
    +repo = ecr.Repository(
    +    self, "repository",
    +    removal_policy=core.RemovalPolicy.DESTROY,
    +)
     
    -job_def = batch.JobDefinition(
    -    self, "job-definition",
    -    container=batch.JobDefinitionContainer(
    -        image=ecs.ContainerImage.from_ecr_repository(repo), #
    -        ...
    -    ),
    -    ...
    -)
    +job_def = batch.JobDefinition( + self, "job-definition", + container=batch.JobDefinitionContainer( + image=ecs.ContainerImage.from_ecr_repository(repo), # + ... + ), + ... +)
    • で,新規の ECR を作成している.

      @@ -32912,89 +32912,89 @@ import name

    さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

    ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

    今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

    -
    sh
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    -(.env) $ cd notebook
    -(.env) $ jupyter notebook
    +
    sh
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook
    # .env の仮想環境にいることを確認
    +(.env) $ cd notebook
    +(.env) $ jupyter notebook

    Jupyter notebook が起動したら, run_single.ipynb を開く.

    最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

    -
    python
    # [1]
    -import boto3
    -import argparse
    +
    python
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
     
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    -import boto3
    -import argparse
    +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    +    resp = client.submit_job(
    +        jobName=title,
    +        jobQueue="SimpleBatchjob-queue",
    +        jobDefinition="SimpleBatchjob-definition",
    +        containerOverrides={
    +            "command": ["--lr", str(lr),
    +                        "--momentum", str(momentum),
    +                        "--epochs", str(epochs),
    +                        "--uploadS3", "true"]
    +        }
    +    )
    +    print("Job submitted!")
    +    print("job name", resp["jobName"], "job ID", resp["jobId"])
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    client = session.client("batch")
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    client = session.client("batch")
     
    -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
    -    resp = client.submit_job(
    -        jobName=title,
    -        jobQueue="SimpleBatchjob-queue",
    -        jobDefinition="SimpleBatchjob-definition",
    -        containerOverrides={
    -            "command": ["--lr", str(lr),
    -                        "--momentum", str(momentum),
    -                        "--epochs", str(epochs),
    -                        "--uploadS3", "true"]
    -        }
    -    )
    -    print("Job submitted!")
    -    print("job name", resp["jobName"], "job ID", resp["jobId"])
    + title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "") + resp = client.submit_job( + jobName=title, + jobQueue="SimpleBatchjob-queue", + jobDefinition="SimpleBatchjob-definition", + containerOverrides={ + "command": ["--lr", str(lr), + "--momentum", str(momentum), + "--epochs", str(epochs), + "--uploadS3", "true"] + } + ) + print("Job submitted!") + print("job name", resp["jobName"], "job ID", resp["jobId"])

    submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

    -
    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    +
    sh
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
    $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

    ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

    AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

    -
    python
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    containerOverrides={
    -    "command": ["--lr", str(lr),
    -                "--momentum", str(momentum),
    -                "--epochs", str(epochs),
    -                "--uploadS3", "true"]
    -}
    +
    python
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}
    containerOverrides={
    +    "command": ["--lr", str(lr),
    +                "--momentum", str(momentum),
    +                "--epochs", str(epochs),
    +                "--uploadS3", "true"]
    +}

    続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

    -
    python
    # [4]
    -submit_job(0.01, 0.1, 100)
    # [4]
    -submit_job(0.01, 0.1, 100)
    +
    python
    # [4]
    +submit_job(0.01, 0.1, 100)
    # [4]
    +submit_job(0.01, 0.1, 100)

    AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

    もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは AWS CLI のインストール), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

    [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

    @@ -33006,124 +33006,124 @@ import name

    S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

    ジョブの実行結果は S3 に保存される

    さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

    -
    python
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    +
    python
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    # [5]
    -import pandas as pd
    -import io
    -from matplotlib import pyplot as plt
    +# [7]
    +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    +df = read_table_from_s3(
    +    bucket_name,
    +    "metrics_lr0.0100_m0.1000.csv"
    +)
    # [5]
    +import pandas as pd
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
    -df = read_table_from_s3(
    -    bucket_name,
    -    "metrics_lr0.0100_m0.1000.csv"
    -)
    +# [7] +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu" +df = read_table_from_s3( + bucket_name, + "metrics_lr0.0100_m0.1000.csv" +)

    [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

    続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

    -
    python
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    +
    python
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
     
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
     
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
     
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    -x = [i for i in range(df.shape[0])]
    -ax1.plot(x, df["train_loss"], label="Train")
    -ax1.plot(x, df["val_loss"], label="Val")
    -ax2.plot(x, df["val_accuracy"])
    +print("Best loss:", df["val_loss"].min())
    +print("Best loss epoch:", df["val_loss"].argmin())
    +print("Best accuracy:", df["val_accuracy"].max())
    +print("Best accuracy epoch:", df["val_accuracy"].argmax())
    # [9]
    +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
    +x = [i for i in range(df.shape[0])]
    +ax1.plot(x, df["train_loss"], label="Train")
    +ax1.plot(x, df["val_loss"], label="Val")
    +ax2.plot(x, df["val_accuracy"])
     
    -ax1.set_xlabel("Epochs")
    -ax1.set_ylabel("Loss")
    -ax1.legend()
    +ax1.set_xlabel("Epochs")
    +ax1.set_ylabel("Loss")
    +ax1.legend()
     
    -ax2.set_xlabel("Epochs")
    -ax2.set_ylabel("Accuracy")
    +ax2.set_xlabel("Epochs")
    +ax2.set_ylabel("Accuracy")
     
    -print("Best loss:", df["val_loss"].min())
    -print("Best loss epoch:", df["val_loss"].argmin())
    -print("Best accuracy:", df["val_accuracy"].max())
    -print("Best accuracy epoch:", df["val_accuracy"].argmax())
    +print("Best loss:", df["val_loss"].min()) +print("Best loss epoch:", df["val_loss"].argmin()) +print("Best accuracy:", df["val_accuracy"].max()) +print("Best accuracy epoch:", df["val_accuracy"].argmax())

    AWS Batch で行った MNIST モデルの学習の結果

    並列に複数の Job を実行する

    さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

    先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

    セル [1], [2], [3] は run_single.ipynb と同一である.

    -
    python
    # [1]
    -import boto3
    -import argparse
    +
    python
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    # [1]
    -import boto3
    -import argparse
    +# [3]
    +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    +    # ...省略...
    # [1]
    +import boto3
    +import argparse
     
    -# [2]
    -# AWS 認証ヘルパー ...省略...
    +# [2]
    +# AWS 認証ヘルパー ...省略...
     
    -# [3]
    -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
    -    # ...省略...
    +# [3] +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None): + # ...省略...

    セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

    -
    python
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    # [4]
    -for lr in [0.1, 0.01, 0.001]:
    -    for m in [0.5, 0.1, 0.05]:
    -        submit_job(lr, m, 100)
    +
    python
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)
    # [4]
    +for lr in [0.1, 0.01, 0.001]:
    +    for m in [0.5, 0.1, 0.05]:
    +        submit_job(lr, m, 100)

    セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

    複数のジョブを同時投入したときの Batch コンソール

    次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

    @@ -33133,81 +33133,81 @@ import name

    ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

    以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

    さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

    -
    python
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    +
    python
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
     
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
     
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
     
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    # [5]
    -import pandas as pd
    -import numpy as np
    -import io
    -from matplotlib import pyplot as plt
    +for i in range(3):
    +    for j in range(3):
    +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    +                       ha="center", va="center", color="w")
    # [5]
    +import pandas as pd
    +import numpy as np
    +import io
    +from matplotlib import pyplot as plt
     
    -# [6]
    -def read_table_from_s3(bucket_name, key, profile_name=None):
    -    if profile_name is None:
    -        session = boto3.Session()
    -    else:
    -        session = boto3.Session(profile_name=profile_name)
    -    s3 = session.resource("s3")
    -    bucket = s3.Bucket(bucket_name)
    +# [6]
    +def read_table_from_s3(bucket_name, key, profile_name=None):
    +    if profile_name is None:
    +        session = boto3.Session()
    +    else:
    +        session = boto3.Session(profile_name=profile_name)
    +    s3 = session.resource("s3")
    +    bucket = s3.Bucket(bucket_name)
     
    -    obj = bucket.Object(key).get().get("Body")
    -    df = pd.read_csv(obj)
    +    obj = bucket.Object(key).get().get("Body")
    +    df = pd.read_csv(obj)
     
    -    return df
    +    return df
     
    -# [7]
    -grid = np.zeros((3,3))
    -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    -        grid[i,j] = df["val_accuracy"].max()
    +# [7]
    +grid = np.zeros((3,3))
    +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
    +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
    +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
    +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
    +        grid[i,j] = df["val_accuracy"].max()
     
    -# [8]
    -fig, ax = plt.subplots(figsize=(6,6))
    -ax.set_aspect('equal')
    +# [8]
    +fig, ax = plt.subplots(figsize=(6,6))
    +ax.set_aspect('equal')
     
    -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
    +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
     
    -for i in range(3):
    -    for j in range(3):
    -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
    -                       ha="center", va="center", color="w")
    +for i in range(3): + for j in range(3): + text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}", + ha="center", va="center", color="w")

    最終的に出力されるプロットが figure_title である.

    ハイパーパラメータのグリッドサーチの結果

    このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

    @@ -33220,9 +33220,9 @@ import name

    ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

    ECR から Docker image を削除する

    あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

    -
    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    +
    sh
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
    $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

    image の削除が完了したうえで,次のコマンドでスタックを削除する.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

    本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

    ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, Hands-on #2: AWS でディープラーニングを実践 で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを Hands-on #3: AWS で自動質問回答ボットを走らせる を参考に構築する.

    @@ -33343,59 +33343,59 @@ import name

    Lambda チュートリアルの概要

    このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    -
    py
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    +
    py
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
     
    -class SimpleLambda(core.Stack):
    +class SimpleLambda(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    #
    -FUNC = """
    -import time
    -from random import choice, randint
    -def handler(event, context):
    -    time.sleep(randint(2,5))
    -    sushi = ["salmon", "tuna", "squid"]
    -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    -    print(message)
    -    return message
    -"""
    +        #
    +        handler = _lambda.Function(
    +            self, 'LambdaHandler',
    +            runtime=_lambda.Runtime.PYTHON_3_7,
    +            code=_lambda.Code.from_inline(FUNC),
    +            handler="index.handler",
    +            memory_size=128,
    +            timeout=core.Duration.seconds(10),
    +            dead_letter_queue_enabled=True,
    +        )
    #
    +FUNC = """
    +import time
    +from random import choice, randint
    +def handler(event, context):
    +    time.sleep(randint(2,5))
    +    sushi = ["salmon", "tuna", "squid"]
    +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
    +    print(message)
    +    return message
    +"""
     
    -class SimpleLambda(core.Stack):
    +class SimpleLambda(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        handler = _lambda.Function(
    -            self, 'LambdaHandler',
    -            runtime=_lambda.Runtime.PYTHON_3_7,
    -            code=_lambda.Code.from_inline(FUNC),
    -            handler="index.handler",
    -            memory_size=128,
    -            timeout=core.Duration.seconds(10),
    -            dead_letter_queue_enabled=True,
    -        )
    + # + handler = _lambda.Function( + self, 'LambdaHandler', + runtime=_lambda.Runtime.PYTHON_3_7, + code=_lambda.Code.from_inline(FUNC), + handler="index.handler", + memory_size=128, + timeout=core.Duration.seconds(10), + dead_letter_queue_enabled=True, + )
    • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

      @@ -33427,25 +33427,25 @@ import name

    上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/lambda
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/lambda
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

    @@ -33456,15 +33456,15 @@ import name

    Lambda 関数の実行

    それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

    以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

    -
    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX
    +
    sh
    $ python invoke_one.py XXXX
    $ python invoke_one.py XXXX

    すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

    さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

    次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

    -
    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100
    +
    sh
    $ python invoke_many.py XXXX 100
    $ python invoke_many.py XXXX 100

    すると次のような出力が得られるはずだ.

    -
    sh
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    ....................................................................................................
    -Submitted 100 tasks to Lambda!
    +
    sh
    ....................................................................................................
    +Submitted 100 tasks to Lambda!
    ....................................................................................................
    +Submitted 100 tasks to Lambda!

    実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

    Lambda コンソール - 関数の実行のモニタリング

    figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

    @@ -33474,44 +33474,44 @@ import name

    興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

    スタックの削除

    最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    DynamoDB ハンズオン

    続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

    このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

    DynamoDB チュートリアルの概要

    このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

    handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    -
    python
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +
    python
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    class SimpleDynamoDb(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +        table = ddb.Table(
    +            self, "SimpleTable",
    +            #
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            #
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            #
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
    class SimpleDynamoDb(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        table = ddb.Table(
    -            self, "SimpleTable",
    -            #
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            #
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            #
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    + table = ddb.Table( + self, "SimpleTable", + # + partition_key=ddb.Attribute( + name="item_id", + type=ddb.AttributeType.STRING + ), + # + billing_mode=ddb.BillingMode.PAY_PER_REQUEST, + # + removal_policy=core.RemovalPolicy.DESTROY + )

    このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

    • @@ -33526,25 +33526,25 @@ import name

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/dynamodb
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/dynamodb
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

    @@ -33554,167 +33554,167 @@ import name

    データの読み書き

    それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

    まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

    -
    python
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    +
    python
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
     
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    import boto3
    -from uuid import uuid4
    -ddb = boto3.resource('dynamodb')
    +def write_item(table_name):
    +    table = ddb.Table(table_name)
    +    table.put_item(
    +    Item={
    +        'item_id': str(uuid4()),
    +        'first_name': 'John',
    +        'last_name': 'Doe',
    +        'age': 25,
    +        }
    +    )
    import boto3
    +from uuid import uuid4
    +ddb = boto3.resource('dynamodb')
     
    -def write_item(table_name):
    -    table = ddb.Table(table_name)
    -    table.put_item(
    -    Item={
    -        'item_id': str(uuid4()),
    -        'first_name': 'John',
    -        'last_name': 'Doe',
    -        'age': 25,
    -        }
    -    )
    +def write_item(table_name): + table = ddb.Table(table_name) + table.put_item( + Item={ + 'item_id': str(uuid4()), + 'first_name': 'John', + 'last_name': 'Doe', + 'age': 25, + } + )

    コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

    では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

    -
    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX
    +
    sh
    $ python simple_write.py XXXX
    $ python simple_write.py XXXX

    新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

    DynamoDB に新しい要素が追加されたことを確認

    boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

    -
    python
    import boto3
    -ddb = boto3.resource('dynamodb')
    +
    python
    import boto3
    +ddb = boto3.resource('dynamodb')
     
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    import boto3
    -ddb = boto3.resource('dynamodb')
    +def scan_table(table_name):
    +    table = ddb.Table(table_name)
    +    items = table.scan().get("Items")
    +    print(items)
    import boto3
    +ddb = boto3.resource('dynamodb')
     
    -def scan_table(table_name):
    -    table = ddb.Table(table_name)
    -    items = table.scan().get("Items")
    -    print(items)
    +def scan_table(table_name): + table = ddb.Table(table_name) + items = table.scan().get("Items") + print(items)

    table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

    次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

    -
    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX
    +
    sh
    $ python simple_read.py XXXX
    $ python simple_read.py XXXX

    先ほど書き込んだ要素が出力されることを確認しよう.

    大量のデータの読み書き

    DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

    そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

    次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

    -
    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000
    +
    sh
    $ python batch_rw.py XXXX write 1000
    $ python batch_rw.py XXXX write 1000

    このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

    さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

    -
    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2
    +
    sh
    $ python batch_rw.py XXXX search_under_age 2
    $ python batch_rw.py XXXX search_under_age 2

    上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

    スタックの削除

    DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

    これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    S3 ハンズオン

    最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

    figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

    S3 チュートリアルの概要

    このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

    -
    python
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +
    python
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    class SimpleS3(core.Stack):
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +        # S3 bucket to store data
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
    class SimpleS3(core.Stack):
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        # S3 bucket to store data
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    + # S3 bucket to store data + bucket = s3.Bucket( + self, "bucket", + removal_policy=core.RemovalPolicy.DESTROY, + auto_delete_objects=True, + )

    s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

    デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

    デプロイ

    デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd handson/serverless/s3
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd handson/serverless/s3
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

    デプロイ実行後の出力

    データの読み書き

    スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

    まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

    -
    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt
    +
    sh
    $ echo "Hello world!" >> tmp.txt
    $ echo "Hello world!" >> tmp.txt

    ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

    -
    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt
    +
    sh
    $ python simple_s3.py XXXX upload tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt

    simple_s3.py のアップロードを担当している部分を以下に抜粋する.

    -
    python
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    +
    python
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if key is None:
    -        key = os.path.basename(filename)
    +    if key is None:
    +        key = os.path.basename(filename)
     
    -    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    -    bucket = s3.Bucket(bucket_name)
    +    bucket.upload_file(filename, key)
    def upload_file(bucket_name, filename, key=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if key is None:
    -        key = os.path.basename(filename)
    +    if key is None:
    +        key = os.path.basename(filename)
     
    -    bucket.upload_file(filename, key)
    + bucket.upload_file(filename, key)

    bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

    S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

    -
    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    +
    sh
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
    $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

    ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

    ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

    S3 バケットの中のファイル一覧

    ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

    オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

    次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

    -
    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt
    +
    sh
    $ python simple_s3.py XXXX download tmp.txt
    $ python simple_s3.py XXXX download tmp.txt

    simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

    -
    python
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    +
    python
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if filename is None:
    -        filename = os.path.basename(key)
    +    if filename is None:
    +        filename = os.path.basename(key)
     
    -    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    -    bucket = s3.Bucket(bucket_name)
    +    bucket.download_file(key, filename)
    def download_file(bucket_name, key, filename=None):
    +    bucket = s3.Bucket(bucket_name)
     
    -    if filename is None:
    -        filename = os.path.basename(key)
    +    if filename is None:
    +        filename = os.path.basename(key)
     
    -    bucket.download_file(key, filename)
    + bucket.download_file(key, filename)

    S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

    スタックの削除

    以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    Hands-on #6: Bashoutter

    さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

    ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

    @@ -33750,197 +33750,197 @@ import name

    それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

    -
    python
    class Bashoutter(core.Stack):
    +
    python
    class Bashoutter(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
     
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
     
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
     
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
     
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
     
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    class Bashoutter(core.Stack):
    +        haiku_item_id = haiku.add_resource("{item_id}")
    +        haiku_item_id.add_method(
    +            "PATCH",
    +            apigw.LambdaIntegration(patch_haiku_lambda)
    +        )
    +        haiku_item_id.add_method(
    +            "DELETE",
    +            apigw.LambdaIntegration(delete_haiku_lambda)
    +        )
    class Bashoutter(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        # dynamoDB table to store haiku
    -        table = ddb.Table(
    -            self, "Bashoutter-Table",
    -            partition_key=ddb.Attribute(
    -                name="item_id",
    -                type=ddb.AttributeType.STRING
    -            ),
    -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        # dynamoDB table to store haiku
    +        table = ddb.Table(
    +            self, "Bashoutter-Table",
    +            partition_key=ddb.Attribute(
    +                name="item_id",
    +                type=ddb.AttributeType.STRING
    +            ),
    +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "Bashoutter-Bucket",
    -            website_index_document="index.html",
    -            public_read_access=True,
    -            removal_policy=core.RemovalPolicy.DESTROY
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "Bashoutter-Bucket",
    +            website_index_document="index.html",
    +            public_read_access=True,
    +            removal_policy=core.RemovalPolicy.DESTROY
    +        )
     
    -        common_params = {
    -            "runtime": _lambda.Runtime.PYTHON_3_7,
    -            "environment": {
    -                "TABLE_NAME": table.table_name
    -            }
    -        }
    +        common_params = {
    +            "runtime": _lambda.Runtime.PYTHON_3_7,
    +            "environment": {
    +                "TABLE_NAME": table.table_name
    +            }
    +        }
     
    -        #
    -        # define Lambda functions
    -        get_haiku_lambda = _lambda.Function(
    -            self, "GetHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.get_haiku",
    -            memory_size=512,
    -            **common_params,
    -        )
    -        post_haiku_lambda = _lambda.Function(
    -            self, "PostHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.post_haiku",
    -            **common_params,
    -        )
    -        patch_haiku_lambda = _lambda.Function(
    -            self, "PatchHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.patch_haiku",
    -            **common_params,
    -        )
    -        delete_haiku_lambda = _lambda.Function(
    -            self, "DeleteHaiku",
    -            code=_lambda.Code.from_asset("api"),
    -            handler="api.delete_haiku",
    -            **common_params,
    -        )
    +        #
    +        # define Lambda functions
    +        get_haiku_lambda = _lambda.Function(
    +            self, "GetHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.get_haiku",
    +            memory_size=512,
    +            **common_params,
    +        )
    +        post_haiku_lambda = _lambda.Function(
    +            self, "PostHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.post_haiku",
    +            **common_params,
    +        )
    +        patch_haiku_lambda = _lambda.Function(
    +            self, "PatchHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.patch_haiku",
    +            **common_params,
    +        )
    +        delete_haiku_lambda = _lambda.Function(
    +            self, "DeleteHaiku",
    +            code=_lambda.Code.from_asset("api"),
    +            handler="api.delete_haiku",
    +            **common_params,
    +        )
     
    -        #
    -        # grant permissions
    -        table.grant_read_data(get_haiku_lambda)
    -        table.grant_read_write_data(post_haiku_lambda)
    -        table.grant_read_write_data(patch_haiku_lambda)
    -        table.grant_read_write_data(delete_haiku_lambda)
    +        #
    +        # grant permissions
    +        table.grant_read_data(get_haiku_lambda)
    +        table.grant_read_write_data(post_haiku_lambda)
    +        table.grant_read_write_data(patch_haiku_lambda)
    +        table.grant_read_write_data(delete_haiku_lambda)
     
    -        #
    -        # define API Gateway
    -        api = apigw.RestApi(
    -            self, "BashoutterApi",
    -            default_cors_preflight_options=apigw.CorsOptions(
    -                allow_origins=apigw.Cors.ALL_ORIGINS,
    -                allow_methods=apigw.Cors.ALL_METHODS,
    -            )
    -        )
    +        #
    +        # define API Gateway
    +        api = apigw.RestApi(
    +            self, "BashoutterApi",
    +            default_cors_preflight_options=apigw.CorsOptions(
    +                allow_origins=apigw.Cors.ALL_ORIGINS,
    +                allow_methods=apigw.Cors.ALL_METHODS,
    +            )
    +        )
     
    -        haiku = api.root.add_resource("haiku")
    -        haiku.add_method(
    -            "GET",
    -            apigw.LambdaIntegration(get_haiku_lambda)
    -        )
    -        haiku.add_method(
    -            "POST",
    -            apigw.LambdaIntegration(post_haiku_lambda)
    -        )
    +        haiku = api.root.add_resource("haiku")
    +        haiku.add_method(
    +            "GET",
    +            apigw.LambdaIntegration(get_haiku_lambda)
    +        )
    +        haiku.add_method(
    +            "POST",
    +            apigw.LambdaIntegration(post_haiku_lambda)
    +        )
     
    -        haiku_item_id = haiku.add_resource("{item_id}")
    -        haiku_item_id.add_method(
    -            "PATCH",
    -            apigw.LambdaIntegration(patch_haiku_lambda)
    -        )
    -        haiku_item_id.add_method(
    -            "DELETE",
    -            apigw.LambdaIntegration(delete_haiku_lambda)
    -        )
    + haiku_item_id = haiku.add_resource("{item_id}") + haiku_item_id.add_method( + "PATCH", + apigw.LambdaIntegration(patch_haiku_lambda) + ) + haiku_item_id.add_method( + "DELETE", + apigw.LambdaIntegration(delete_haiku_lambda) + )
    • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

      @@ -33961,17 +33961,17 @@ import name

    それぞれの項目について,もう少し詳しく説明しよう.

    Public access mode の S3 バケット

    S3 のバケットを作成しているコードを見てみよう.

    -
    python
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    bucket = s3.Bucket(
    -    self, "Bashoutter-Bucket",
    -    website_index_document="index.html",
    -    public_read_access=True,
    -    removal_policy=core.RemovalPolicy.DESTROY
    -)
    +
    python
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)
    bucket = s3.Bucket(
    +    self, "Bashoutter-Bucket",
    +    website_index_document="index.html",
    +    public_read_access=True,
    +    removal_policy=core.RemovalPolicy.DESTROY
    +)

    ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

    なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

    より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

    @@ -33982,72 +33982,72 @@ import name

    今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

    API のハンドラ関数

    API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

    -
    python
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    get_haiku_lambda = _lambda.Function(
    -    self, "GetHaiku",
    -    code=_lambda.Code.from_asset("api"),
    -    handler="api.get_haiku",
    -    memory_size=512,
    -    **common_params
    -)
    +
    python
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)
    get_haiku_lambda = _lambda.Function(
    +    self, "GetHaiku",
    +    code=_lambda.Code.from_asset("api"),
    +    handler="api.get_haiku",
    +    memory_size=512,
    +    **common_params
    +)

    簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

    次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

    -
    python
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    +
    python
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
     
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
     
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    ddb = boto3.resource("dynamodb")
    -table = ddb.Table(os.environ["TABLE_NAME"])
    +        status_code = 200
    +        resp = response.get("Items")
    +    except Exception as e:
    +        status_code = 500
    +        resp = {"description": f"Internal server error. {str(e)}"}
    +    return {
    +        "statusCode": status_code,
    +        "headers": HEADERS,
    +        "body": json.dumps(resp, cls=DecimalEncoder)
    +    }
    ddb = boto3.resource("dynamodb")
    +table = ddb.Table(os.environ["TABLE_NAME"])
     
    -def get_haiku(event, context):
    -    """
    -    handler for GET /haiku
    -    """
    -    try:
    -        response = table.scan()
    +def get_haiku(event, context):
    +    """
    +    handler for GET /haiku
    +    """
    +    try:
    +        response = table.scan()
     
    -        status_code = 200
    -        resp = response.get("Items")
    -    except Exception as e:
    -        status_code = 500
    -        resp = {"description": f"Internal server error. {str(e)}"}
    -    return {
    -        "statusCode": status_code,
    -        "headers": HEADERS,
    -        "body": json.dumps(resp, cls=DecimalEncoder)
    -    }
    + status_code = 200 + resp = response.get("Items") + except Exception as e: + status_code = 500 + resp = {"description": f"Internal server error. {str(e)}"} + return { + "statusCode": status_code, + "headers": HEADERS, + "body": json.dumps(resp, cls=DecimalEncoder) + }

    response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

    上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

    GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

    AWS における権限の管理 (IAM)

    以下の部分のコードに注目してほしい.

    -
    python
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    -table.grant_read_write_data(post_haiku_lambda)
    -table.grant_read_write_data(patch_haiku_lambda)
    -table.grant_read_write_data(delete_haiku_lambda)
    +
    python
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)
    table.grant_read_data(get_haiku_lambda)
    +table.grant_read_write_data(post_haiku_lambda)
    +table.grant_read_write_data(patch_haiku_lambda)
    +table.grant_read_write_data(delete_haiku_lambda)

    これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.

    CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

    各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

    @@ -34058,69 +34058,69 @@ import name

    API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

    API Gateway の利用料金設定 (参照)
    Number of Requests (per month)Price (per million)

    First 333 million

    $4.25

    Next 667 million

    $3.53

    Next 19 billion

    $3.00

    Over 20 billion

    $1.91

    ソースコードの該当箇所を見てみよう.

    -
    python
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    +
    python
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
     
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
     
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    #
    -api = apigw.RestApi(
    -    self, "BashoutterApi",
    -    default_cors_preflight_options=apigw.CorsOptions(
    -        allow_origins=apigw.Cors.ALL_ORIGINS,
    -        allow_methods=apigw.Cors.ALL_METHODS,
    -    )
    -)
    +#
    +haiku_item_id = haiku.add_resource("{item_id}")
    +#
    +haiku_item_id.add_method(
    +    "PATCH",
    +    apigw.LambdaIntegration(patch_haiku_lambda)
    +)
    +haiku_item_id.add_method(
    +    "DELETE",
    +    apigw.LambdaIntegration(delete_haiku_lambda)
    +)
    #
    +api = apigw.RestApi(
    +    self, "BashoutterApi",
    +    default_cors_preflight_options=apigw.CorsOptions(
    +        allow_origins=apigw.Cors.ALL_ORIGINS,
    +        allow_methods=apigw.Cors.ALL_METHODS,
    +    )
    +)
     
    -#
    -haiku = api.root.add_resource("haiku")
    -#
    -haiku.add_method(
    -    "GET",
    -    apigw.LambdaIntegration(get_haiku_lambda)
    -)
    -haiku.add_method(
    -    "POST",
    -    apigw.LambdaIntegration(post_haiku_lambda)
    -)
    +#
    +haiku = api.root.add_resource("haiku")
    +#
    +haiku.add_method(
    +    "GET",
    +    apigw.LambdaIntegration(get_haiku_lambda)
    +)
    +haiku.add_method(
    +    "POST",
    +    apigw.LambdaIntegration(post_haiku_lambda)
    +)
     
    -#
    -haiku_item_id = haiku.add_resource("{item_id}")
    -#
    -haiku_item_id.add_method(
    -    "PATCH",
    -    apigw.LambdaIntegration(patch_haiku_lambda)
    -)
    -haiku_item_id.add_method(
    -    "DELETE",
    -    apigw.LambdaIntegration(delete_haiku_lambda)
    -)
    +# +haiku_item_id = haiku.add_resource("{item_id}") +# +haiku_item_id.add_method( + "PATCH", + apigw.LambdaIntegration(patch_haiku_lambda) +) +haiku_item_id.add_method( + "DELETE", + apigw.LambdaIntegration(delete_haiku_lambda) +)
    • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

      @@ -34143,25 +34143,25 @@ import name

    API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

    アプリケーションのデプロイ

    アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

    -
    sh
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    +
    sh
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    # プロジェクトのディレクトリに移動
    -$ cd intro-aws/handson/bashoutter
    +# デプロイを実行
    +$ cdk deploy
    # プロジェクトのディレクトリに移動
    +$ cd intro-aws/handson/bashoutter
     
    -# venv を作成し,依存ライブラリのインストールを行う
    -$ python3 -m venv .env
    -$ source .env/bin/activate
    -$ pip install -r requirements.txt
    +# venv を作成し,依存ライブラリのインストールを行う
    +$ python3 -m venv .env
    +$ source .env/bin/activate
    +$ pip install -r requirements.txt
     
    -# デプロイを実行
    -$ cdk deploy
    +# デプロイを実行 +$ cdk deploy

    デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

    CDKデプロイ実行後の出力

    AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

    @@ -34177,109 +34177,109 @@ import name

    それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

    ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

    まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

    -
    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX
    +
    sh
    $ export ENDPOINT_URL=XXXX
    $ export ENDPOINT_URL=XXXX

    次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

    -
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"
    +
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    $ http GET "${ENDPOINT_URL}/haiku"

    現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

    それでは次に, POST /haiku を使って俳句を投稿してみよう.

    -
    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    -username="松尾芭蕉" \
    -first="閑さや" \
    -second="岩にしみ入る" \
    -third="蝉の声"
    +
    sh
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"
    $ http POST "${ENDPOINT_URL}/haiku" \
    +username="松尾芭蕉" \
    +first="閑さや" \
    +second="岩にしみ入る" \
    +third="蝉の声"

    次のような出力が得られるだろう.

    -
    sh
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    HTTP/1.1 201 Created
    -Connection: keep-alive
    -Content-Length: 49
    -Content-Type: application/json
    -....
    -{
    -    "description": "Successfully added a new haiku"
    -}
    +
    sh
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}
    HTTP/1.1 201 Created
    +Connection: keep-alive
    +Content-Length: 49
    +Content-Type: application/json
    +....
    +{
    +    "description": "Successfully added a new haiku"
    +}

    新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

    -
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
     
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    +HTTP/1.1 200 OK
    +Connection: keep-alive
    +Content-Length: 258
    +Content-Type: application/json
    +...
    +[
    +    {
    +        "created_at": "2020-07-06T02:46:04+00:00",
    +        "first": "閑さや",
    +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    +        "likes": 0.0,
    +        "second": "岩にしみ入る",
    +        "third": "蝉の声",
    +        "username": "松尾芭蕉"
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
     
    -HTTP/1.1 200 OK
    -Connection: keep-alive
    -Content-Length: 258
    -Content-Type: application/json
    -...
    -[
    -    {
    -        "created_at": "2020-07-06T02:46:04+00:00",
    -        "first": "閑さや",
    -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
    -        "likes": 0.0,
    -        "second": "岩にしみ入る",
    -        "third": "蝉の声",
    -        "username": "松尾芭蕉"
    -    }
    -]
    +HTTP/1.1 200 OK +Connection: keep-alive +Content-Length: 258 +Content-Type: application/json +... +[ + { + "created_at": "2020-07-06T02:46:04+00:00", + "first": "閑さや", + "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b", + "likes": 0.0, + "second": "岩にしみ入る", + "third": "蝉の声", + "username": "松尾芭蕉" + } +]

    素晴らしい!

    次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

    -
    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    +
    sh
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
    $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"

    {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

    -
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    $ http GET "${ENDPOINT_URL}/haiku"
    -...
    -[
    -    {
    -        ...
    -        "likes": 1.0,
    -        ...
    -    }
    -]
    +
    sh
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]
    $ http GET "${ENDPOINT_URL}/haiku"
    +...
    +[
    +    {
    +        ...
    +        "likes": 1.0,
    +        ...
    +    }
    +]

    最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

    -
    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    +
    sh
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
    $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"

    再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

    これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

    大量の API リクエストをシミュレートする

    さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

    handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

    テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

    -
    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300
    +
    sh
    $ python client.py $ENDPOINT_URL post_many 300
    $ python client.py $ENDPOINT_URL post_many 300

    数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

    先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

    -
    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database
    +
    sh
    $ python client.py $ENDPOINT_URL clear_database
    $ python client.py $ENDPOINT_URL clear_database

    Bashoutter GUI を動かしてみる

    前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている (figure_title 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

    CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

    -
    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    +
    sh
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
    $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

    コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

    なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

    アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

    @@ -34291,11 +34291,11 @@ import name

    これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

    Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

    コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

    -
    sh
    $ cdk destroy
    $ cdk destroy
    +
    sh
    $ cdk destroy
    $ cdk destroy

    CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

    コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

    コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

    -
    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive
    +
    sh
    $ aws s3 rm <BUCKET NAME> --recursive
    $ aws s3 rm <BUCKET NAME> --recursive

    小括

    ここまでが,本書第三部の内容であった.

    第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. Hands-on #5: サーバーレス入門 では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

    @@ -34396,59 +34396,59 @@ output = json

    vocareum から AWS シークレットキーの発行

    AWS CLI のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    -
    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    -$ unzip awscliv2.zip
    -$ sudo ./aws/install
    +
    sh
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install
    $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    +$ unzip awscliv2.zip
    +$ sudo ./aws/install

    インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

    -
    sh
    $ aws --version
    $ aws --version
    +
    sh
    $ aws --version
    $ aws --version

    インストールができたら,次のコマンドにより初期設定を行う (参照).

    -
    sh
    $ aws configure
    $ aws configure
    +
    sh
    $ aws configure
    $ aws configure

    コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

    このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

    -
    sh
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +
    sh
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
     
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    $ cat ~/.aws/credentials
    -[default]
    -aws_access_key_id = XXXXXXXXXXXXXXXXXX
    -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
    +$ cat ~/.aws/config
    +[profile default]
    +region = ap-northeast-1
    +output = json
    $ cat ~/.aws/credentials
    +[default]
    +aws_access_key_id = XXXXXXXXXXXXXXXXXX
    +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
     
    -$ cat ~/.aws/config
    -[profile default]
    -region = ap-northeast-1
    -output = json
    +$ cat ~/.aws/config +[profile default] +region = ap-northeast-1 +output = json

    ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

    デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

    AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

    -
    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile
    +
    sh
    $ aws s3 ls --profile myprofile
    $ aws s3 ls --profile myprofile

    のように, --profile というオプションをつけてコマンドを実行する.

    いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

    -
    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile
    +
    sh
    $ export AWS_PROFILE=myprofile
    $ export AWS_PROFILE=myprofile

    あるいは,認証情報などを環境変数に設定するテクニックもある.

    -
    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    -export AWS_SECRET_ACCESS_KEY=YYYYYY
    -export AWS_DEFAULT_REGION=ap-northeast-1
    +
    sh
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1
    export AWS_ACCESS_KEY_ID=XXXXXX
    +export AWS_SECRET_ACCESS_KEY=YYYYYY
    +export AWS_DEFAULT_REGION=ap-northeast-1

    これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

    AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

    AWS CDK のインストール

    読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

    Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

    -
    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk
    +
    sh
    $ sudo npm install -g aws-cdk
    $ sudo npm install -g aws-cdk

    本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

    -
    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100
    +
    sh
    $ npm install -g aws-cdk@1.100
    $ npm install -g aws-cdk@1.100

    インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

    -
    sh
    $ cdk --version
    $ cdk --version
    +
    sh
    $ cdk --version
    $ cdk --version

    インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

    -
    sh
    $ cdk bootstrap
    $ cdk bootstrap
    +
    sh
    $ cdk bootstrap
    $ cdk bootstrap

    cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

    AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

    WSL のインストール

    @@ -34459,15 +34459,15 @@ output = json

    まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

    管理者権限での PowerShell の起動

    PowerShell が起動したら、次のコマンドを実行する.

    -
    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    +
    powershell
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

    実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

    次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

    -
    powersh
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    +
    powersh
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

    続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

    そうしたら,再び PowerShell を開き次のコマンドを実行する。

    -
    sh
    wsl --set-default-version 2
    wsl --set-default-version 2
    +
    sh
    wsl --set-default-version 2
    wsl --set-default-version 2

    最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

    Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

    Microsoft store から Ubuntu 20.04 をインストール

    @@ -34483,33 +34483,33 @@ output = json

    Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

    Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

    最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

    -
    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    -$ sudo sh get-docker.sh
    +
    sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh
    $ curl -fsSL https://get.docker.com -o get-docker.sh
    +$ sudo sh get-docker.sh

    デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

    まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

    -
    sh
    $ sudo groupadd docker
    $ sudo groupadd docker
    +
    sh
    $ sudo groupadd docker
    $ sudo groupadd docker

    次に,現在使用しているユーザーを docker グループに加える.

    -
    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER
    +
    sh
    $ sudo usermod -aG docker $USER
    $ sudo usermod -aG docker $USER

    ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

    設定が正しくできているかを確認するため,次のコマンドを実行してみる.

    -
    sh
    $ docker run hello-world
    $ docker run hello-world
    +
    sh
    $ docker run hello-world
    $ docker run hello-world

    sudo なしでコンテナが実行できたならば,設定は完了である.

    Python venv クイックガイド

    他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

    コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

    そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

    venv を使って仮想環境を作成するには,

    -
    sh
    $ python -m venv .env
    $ python -m venv .env
    +
    sh
    $ python -m venv .env
    $ python -m venv .env

    と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

    この新たな仮想環境を起動するには

    -
    sh
    $ source .env/bin/activate
    $ source .env/bin/activate
    +
    sh
    $ source .env/bin/activate
    $ source .env/bin/activate

    と実行する.

    シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

    venv を起動したときのプロンプト

    仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

    Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

    -
    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt
    +
    sh
    $ pip install -r requirements.txt
    $ pip install -r requirements.txt

    と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

    venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

    ハンズオン実行用の Docker image の使い方

    @@ -34517,16 +34517,16 @@ output = json

    ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

    Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

    次のコマンドでコンテナを起動する.

    -
    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest
    +
    sh
    $ docker run -it tomomano/labc:latest
    $ docker run -it tomomano/labc:latest

    初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

    コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

    -
    sh
    root@aws-handson:~/programlisting
    root@aws-handson:~/programlisting
    +
    sh
    root@aws-handson:~/programlisting
    root@aws-handson:~/programlisting

    この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

    -
    sh
    $ cd handson
    $ cd handson
    +
    sh
    $ cd handson
    $ cd handson

    すると,各ハンズオンごとのディレクトリが見つかるはずである.

    あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい (プログラムを実行する など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

    AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

    -
    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    +
    sh
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
    $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

    これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

    /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

    ライセンス

    @@ -34584,7 +34584,7 @@ output = json

    ハンズオン実行用の Docker Image

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    次のコマンドで起動する.

    -
    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc
    +
    sh
    $ docker run -it tomomano/labc
    $ docker run -it tomomano/labc

    この Docker image の使い方や詳細は ハンズオン実行用の Docker image の使い方 に記載している.

    前提知識

    本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OS,プログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.

    @@ -34751,44 +34751,44 @@ output = json

    具体的な API の使用例を見てみよう.

    S3 に新しい保存領域 (Bucket (バケット) とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.

    -
    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    +
    sh
    $ aws s3 mb s3://my-bucket --region ap-northeast-1
    $ aws s3 mb s3://my-bucket --region ap-northeast-1

    上記のコマンドは, my-bucket という名前のバケットを, ap-northeast-1 のリージョンに作成する.

    Python からこれと同じ操作を実行するには, boto3 ライブラリを使って,次のようなスクリプトを実行する.

    -
    python
    import boto3
    +
    python
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    import boto3
    +s3_client = boto3.client("s3", region_name="ap-northeast-1")
    +s3_client.create_bucket(Bucket="my-bucket")
    import boto3
     
    -s3_client = boto3.client("s3", region_name="ap-northeast-1")
    -s3_client.create_bucket(Bucket="my-bucket")
    +s3_client = boto3.client("s3", region_name="ap-northeast-1") +s3_client.create_bucket(Bucket="my-bucket")

    もう一つ例をあげよう.

    新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.

    -
    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    +
    sh
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
    $ aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e

    このコマンドにより, t2.micro というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン (Hands-on #1: 初めての EC2 インスタンスを起動する) で詳しく解説する).

    Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.

    -
    python
    import boto3
    +
    python
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    import boto3
    +ec2_client = boto3.client("ec2")
    +ec2_client.run_instances(
    +    ImageId="ami-xxxxxxxxx",
    +    MinCount=1,
    +    MaxCount=1,
    +    KeyName="MyKeyPair",
    +    InstanceType="t2.micro",
    +    SecurityGroupIds=["sg-903004f8"],
    +    SubnetId="subnet-6e7f829e",
    +)
    import boto3
     
    -ec2_client = boto3.client("ec2")
    -ec2_client.run_instances(
    -    ImageId="ami-xxxxxxxxx",
    -    MinCount=1,
    -    MaxCount=1,
    -    KeyName="MyKeyPair",
    -    InstanceType="t2.micro",
    -    SecurityGroupIds=["sg-903004f8"],
    -    SubnetId="subnet-6e7f829e",
    -)
    +ec2_client = boto3.client("ec2") +ec2_client.run_instances( + ImageId="ami-xxxxxxxxx", + MinCount=1, + MaxCount=1, + KeyName="MyKeyPair", + InstanceType="t2.micro", + SecurityGroupIds=["sg-903004f8"], + SubnetId="subnet-6e7f829e", +)

    以上の例を通じて,API によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる. もちろん,逆の操作 (リソースの削除) も API を使って実行できる.

    ミニ・ハンズオン: AWS CLI を使ってみよう

    ここでは,ミニ・ハンズオンとして,AWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,S3 を使ったファイルの読み書きを実践する (EC2 の操作は少し複雑なので,第一回ハンズオンで行う). aws s3 コマンドの詳しい使い方は 公式ドキュメンテーションを参照.

    @@ -34796,34 +34796,34 @@ output = json

    以下に紹介するハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

    以下のコマンドを実行する前に,AWS の認証情報が正しく設定されていることを確認する. これには ~/.aws/credentials のファイルに設定が書き込まれているか,環境変数 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) が定義されている必要がある. 詳しくは AWS CLI のインストール を参照.

    まずは,S3 にデータの格納領域 (Bucket とよばれる.一般的な OS での"ドライブ"に相当する) を作成するところから始めよう.

    -
    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    -$ echo $bucketName
    -$ aws s3 mb "s3://${bucketName}"
    +
    sh
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"
    $ bucketName="mybucket-$(openssl rand -hex 12)"
    +$ echo $bucketName
    +$ aws s3 mb "s3://${bucketName}"

    S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,bucketName という変数に格納している. そして, aws s3 mb (mb は make bucket の略) によって,新しいバケットを作成する.

    次に,バケットの一覧を取得してみよう.

    -
    sh
    $ aws s3 ls
    +
    sh
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    $ aws s3 ls
     
    -2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe
    +2020-06-07 23:45:44 mybucket-c6f93855550a72b5b66f5efe

    先ほど作成したバケットがリストにあることを確認できる.

    本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に $ がつけてある. $ はコマンドをコピー&ペーストするときは除かなければならない. 逆に,コマンドの出力は $ なしで表示されている.

    次に,バケットにファイルをアップロードする.

    -
    sh
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    -$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    +
    sh
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"
    $ echo "Hello world" > hello_world.txt
    +$ aws s3 cp hello_world.txt "s3://${bucketName}/hello_world.txt"

    上では hello_world.txt というダミーのファイルを作成して,それをアップロードした.

    それでは,バケットの中にあるファイルの一覧を取得してみる.

    -
    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +
    sh
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
    +2020-06-07 23:54:19   13 Bytes hello_world.txt
    $ aws s3 ls "s3://${bucketName}" --human-readable
     
    -2020-06-07 23:54:19   13 Bytes hello_world.txt
    +2020-06-07 23:54:19 13 Bytes hello_world.txt

    先ほどアップロードしたファイルがたしかに存在することがわかる.

    最後に,使い終わったバケットを削除する.

    -
    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force
    +
    sh
    $ aws s3 rb "s3://${bucketName}" --force
    $ aws s3 rb "s3://${bucketName}" --force

    rb は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには --force のオプションを付ける.

    以上のように,AWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.

    Amazon Resource Name (ARN)

    @@ -34839,120 +34839,120 @@ output = json

    そのような観点から,インフラを記述するプログラムタスクを実行するプログラムはある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.

    AWS での静的リソースを管理するための仕組みが, CloudFormation である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使って,AWS のインフラを記述する仕組みである. CloudFormation を使って,たとえば,EC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. また,CloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.

    CloudFormation を記述するには,基本的に JSON (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードは,JSON で記述された CloudFormation ファイルの一例 (抜粋) である.

    -
    json
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +
    json
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    "Resources" : {
    -  ...
    -  "WebServer": {
    -    "Type" : "AWS::EC2::Instance",
    -    "Properties": {
    -      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    -                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    -      "InstanceType"   : { "Ref" : "InstanceType" },
    -      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    -      "KeyName"        : { "Ref" : "KeyName" },
    -      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    -                     "#!/bin/bash -xe\n",
    -                     "yum update -y aws-cfn-bootstrap\n",
    +                     "/opt/aws/bin/cfn-signal -e $? ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    +      ]]}}
    +    },
    +    ...
    +  },
    +  ...
    +},
    "Resources" : {
    +  ...
    +  "WebServer": {
    +    "Type" : "AWS::EC2::Instance",
    +    "Properties": {
    +      "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
    +                        { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
    +      "InstanceType"   : { "Ref" : "InstanceType" },
    +      "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
    +      "KeyName"        : { "Ref" : "KeyName" },
    +      "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
    +                     "#!/bin/bash -xe\n",
    +                     "yum update -y aws-cfn-bootstrap\n",
     
    -                     "/opt/aws/bin/cfn-init -v ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --configsets wordpress_install ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
    +                     "/opt/aws/bin/cfn-init -v ",
    +                     "         --stack ", { "Ref" : "AWS::StackName" },
    +                     "         --resource WebServer ",
    +                     "         --configsets wordpress_install ",
    +                     "         --region ", { "Ref" : "AWS::Region" }, "\n",
     
    -                     "/opt/aws/bin/cfn-signal -e $? ",
    -                     "         --stack ", { "Ref" : "AWS::StackName" },
    -                     "         --resource WebServer ",
    -                     "         --region ", { "Ref" : "AWS::Region" }, "\n"
    -      ]]}}
    -    },
    -    ...
    -  },
    -  ...
    -},
    + "/opt/aws/bin/cfn-signal -e $? ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WebServer ", + " --region ", { "Ref" : "AWS::Region" }, "\n" + ]]}} + }, + ... + }, + ... +},

    ここでは, "WebServer" という名前のつけられた EC2 インスタンスを定義している.かなり長大で複雑な記述であるが,これによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.

    AWS CDK

    前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に"テキスト"を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する). また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.

    そのような悩みを解決してくれるのが, AWS Cloud Development Kit (CDK) である. CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである. CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (GitHub リポジトリ のリリースを見ればその開発のスピードの速さがわかるだろう). CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.

    CDK を使うことで,CloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.

    以下に Python を使った CDK のコードの一例 (抜粋) を示す.

    -
    python
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +
    python
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    from aws_cdk import (
    -    core,
    -    aws_ec2 as ec2,
    -)
    +        host = ec2.Instance(
    +            self, "MyGreatEc2",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            ...
    +        )
    from aws_cdk import (
    +    core,
    +    aws_ec2 as ec2,
    +)
     
    -class MyFirstEc2(core.Stack):
    +class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope, name, **kwargs):
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope, name, **kwargs):
    +        super().__init__(scope, name, **kwargs)
     
    -        vpc = ec2.Vpc(
    -            ... # some parameters
    -        )
    +        vpc = ec2.Vpc(
    +            ... # some parameters
    +        )
     
    -        sg = ec2.SecurityGroup(
    -            ... # some parameters
    -        )
    +        sg = ec2.SecurityGroup(
    +            ... # some parameters
    +        )
     
    -        host = ec2.Instance(
    -            self, "MyGreatEc2",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            ...
    -        )
    + host = ec2.Instance( + self, "MyGreatEc2", + instance_type=ec2.InstanceType("t2.micro"), + machine_image=ec2.MachineImage.latest_amazon_linux(), + vpc=vpc, + ... + )

    このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.

    本書の主題は,CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである. 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.

      @@ -34971,7 +34971,7 @@ output = json

    • AWS CDK: AWS CDK のインストールについては, AWS CDK のインストール を参照.
    • ソースコードのダウンロード: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.
    -
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    +
    sh
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git
    $ git clone https://github.com/tomomano/learn-aws-by-coding.git

    あるいは, https://github.com/tomomano/learn-aws-by-coding のページに行って,右上のダウンロードボタンからダウンロードすることもできる.

    Docker を使用する場合

    Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.

    @@ -34980,95 +34980,95 @@ output = json

    SSH (secure shell) は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.

    SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する (環境構築 を参照).

    SSH コマンドの基本的な使い方を次に示す. <host name> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <user name> は接続する先のユーザー名である.

    -
    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>
    +
    sh
    $ ssh <user name>@<host name>
    $ ssh <user name>@<host name>

    SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,公開鍵暗号方式(Public Key Cryptography)による認証を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,秘密鍵は絶対に漏洩することのないよう注意して管理する

    SSH コマンドでは,ログインのために使用する秘密鍵ファイルを -i もしくは --identity_file のオプションで指定することができる. たとえば,次のように使う.

    -
    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    +
    sh
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>
    $ ssh -i Ec2SecretKey.pem <user name>@<host name>

    アプリケーションの説明

    このハンズオンで作成するアプリケーションの概要を figure_title に示す.

    ハンズオン#1で作製するアプリケーションのアーキテクチャ

    このアプリケーションではまず,VPC (Virtual Private Cloud) を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,EC2 (Elatic Compute Cloud) の仮想サーバーを配置する. さらに,セキュリティのため, Security Group による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーに,SSH を使ってアクセスし,簡単な計算を行う.

    figure_title のようなアプリケーションを,CDK を使って構築する.

    早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (handson/ec2-get-started/app.py).

    -
    python
    class MyFirstEc2(core.Stack):
    +
    python
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    class MyFirstEc2(core.Stack):
    +        #
    +        host = ec2.Instance(
    +            self, "MyFirstEc2Instance",
    +            instance_type=ec2.InstanceType("t2.micro"),
    +            machine_image=ec2.MachineImage.latest_amazon_linux(),
    +            vpc=vpc,
    +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    +            security_group=sg,
    +            key_name=key_name
    +        )
    class MyFirstEc2(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        vpc = ec2.Vpc(
    -            self, "MyFirstEc2-Vpc",
    -            max_azs=1,
    -            cidr="10.10.0.0/23",
    -            subnet_configuration=[
    -                ec2.SubnetConfiguration(
    -                    name="public",
    -                    subnet_type=ec2.SubnetType.PUBLIC,
    -                )
    -            ],
    -            nat_gateways=0,
    -        )
    +        #
    +        vpc = ec2.Vpc(
    +            self, "MyFirstEc2-Vpc",
    +            max_azs=1,
    +            cidr="10.10.0.0/23",
    +            subnet_configuration=[
    +                ec2.SubnetConfiguration(
    +                    name="public",
    +                    subnet_type=ec2.SubnetType.PUBLIC,
    +                )
    +            ],
    +            nat_gateways=0,
    +        )
     
    -        #
    -        sg = ec2.SecurityGroup(
    -            self, "MyFirstEc2Vpc-Sg",
    -            vpc=vpc,
    -            allow_all_outbound=True,
    -        )
    -        sg.add_ingress_rule(
    -            peer=ec2.Peer.any_ipv4(),
    -            connection=ec2.Port.tcp(22),
    -        )
    +        #
    +        sg = ec2.SecurityGroup(
    +            self, "MyFirstEc2Vpc-Sg",
    +            vpc=vpc,
    +            allow_all_outbound=True,
    +        )
    +        sg.add_ingress_rule(
    +            peer=ec2.Peer.any_ipv4(),
    +            connection=ec2.Port.tcp(22),
    +        )
     
    -        #
    -        host = ec2.Instance(
    -            self, "MyFirstEc2Instance",
    -            instance_type=ec2.InstanceType("t2.micro"),
    -            machine_image=ec2.MachineImage.latest_amazon_linux(),
    -            vpc=vpc,
    -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    -            security_group=sg,
    -            key_name=key_name
    -        )
    + # + host = ec2.Instance( + self, "MyFirstEc2Instance", + instance_type=ec2.InstanceType("t2.micro"), + machine_image=ec2.MachineImage.latest_amazon_linux(), + vpc=vpc, + vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC), + security_group=sg, + key_name=key_name + )
    • まず最初に,VPC を定義する.

      @@ -35087,29 +35087,29 @@ output = json

      VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.

      本ハンズオンでは,サーバーは一つしか起動しないので,VPC の恩恵はよく分からないかもしれない.しかし,EC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.

      興味のある読者のために,VPC のコードについてもう少し詳しく説明しよう.

      -
      python
      vpc = ec2.Vpc(
      -    self, "MyFirstEc2-Vpc",
      -    max_azs=1,
      -    cidr="10.10.0.0/23",
      -    subnet_configuration=[
      -        ec2.SubnetConfiguration(
      -            name="public",
      -            subnet_type=ec2.SubnetType.PUBLIC,
      -        )
      -    ],
      -    nat_gateways=0,
      -)
      vpc = ec2.Vpc(
      -    self, "MyFirstEc2-Vpc",
      -    max_azs=1,
      -    cidr="10.10.0.0/23",
      -    subnet_configuration=[
      -        ec2.SubnetConfiguration(
      -            name="public",
      -            subnet_type=ec2.SubnetType.PUBLIC,
      -        )
      -    ],
      -    nat_gateways=0,
      -)
      +
      python
      vpc = ec2.Vpc(
      +    self, "MyFirstEc2-Vpc",
      +    max_azs=1,
      +    cidr="10.10.0.0/23",
      +    subnet_configuration=[
      +        ec2.SubnetConfiguration(
      +            name="public",
      +            subnet_type=ec2.SubnetType.PUBLIC,
      +        )
      +    ],
      +    nat_gateways=0,
      +)
      vpc = ec2.Vpc(
      +    self, "MyFirstEc2-Vpc",
      +    max_azs=1,
      +    cidr="10.10.0.0/23",
      +    subnet_configuration=[
      +        ec2.SubnetConfiguration(
      +            name="public",
      +            subnet_type=ec2.SubnetType.PUBLIC,
      +        )
      +    ],
      +    nat_gateways=0,
      +)
      • max_azs=1 : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので 1 にしている.

        @@ -35127,23 +35127,23 @@ output = json

        Security Group

        Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.

        コードの該当部分を見てみよう.

        -
        python
        sg = ec2.SecurityGroup(
        -    self, "MyFirstEc2Vpc-Sg",
        -    vpc=vpc,
        -    allow_all_outbound=True,
        -)
        -sg.add_ingress_rule(
        -    peer=ec2.Peer.any_ipv4(),
        -    connection=ec2.Port.tcp(22),
        -)
        sg = ec2.SecurityGroup(
        -    self, "MyFirstEc2Vpc-Sg",
        -    vpc=vpc,
        -    allow_all_outbound=True,
        -)
        -sg.add_ingress_rule(
        -    peer=ec2.Peer.any_ipv4(),
        -    connection=ec2.Port.tcp(22),
        -)
        +
        python
        sg = ec2.SecurityGroup(
        +    self, "MyFirstEc2Vpc-Sg",
        +    vpc=vpc,
        +    allow_all_outbound=True,
        +)
        +sg.add_ingress_rule(
        +    peer=ec2.Peer.any_ipv4(),
        +    connection=ec2.Port.tcp(22),
        +)
        sg = ec2.SecurityGroup(
        +    self, "MyFirstEc2Vpc-Sg",
        +    vpc=vpc,
        +    allow_all_outbound=True,
        +)
        +sg.add_ingress_rule(
        +    peer=ec2.Peer.any_ipv4(),
        +    connection=ec2.Port.tcp(22),
        +)

        本ハンズオンでは, SSH による外部からの接続を許容するため, sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22)) により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, allow_all_outbound=True のパラメータを設定している.

        SSH はデフォルトでは 22 番ポートを使用するのが慣例である.

        セキュリティ上の観点からは,SSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.

        @@ -35158,23 +35158,23 @@ output = json

        table_title の価格は us-east-1 のものである. リージョンによって多少価格設定が異なる.

        上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, Spot instance とよばれるインスタンスも存在しする. Spot instance は,AWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.

        EC2 インスタンスを定義しているコードの該当部分を見てみよう.

        -
        python
        host = ec2.Instance(
        -    self, "MyFirstEc2Instance",
        -    instance_type=ec2.InstanceType("t2.micro"),
        -    machine_image=ec2.MachineImage.latest_amazon_linux(),
        -    vpc=vpc,
        -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
        -    security_group=sg,
        -    key_name=key_name
        -)
        host = ec2.Instance(
        -    self, "MyFirstEc2Instance",
        -    instance_type=ec2.InstanceType("t2.micro"),
        -    machine_image=ec2.MachineImage.latest_amazon_linux(),
        -    vpc=vpc,
        -    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
        -    security_group=sg,
        -    key_name=key_name
        -)
        +
        python
        host = ec2.Instance(
        +    self, "MyFirstEc2Instance",
        +    instance_type=ec2.InstanceType("t2.micro"),
        +    machine_image=ec2.MachineImage.latest_amazon_linux(),
        +    vpc=vpc,
        +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
        +    security_group=sg,
        +    key_name=key_name
        +)
        host = ec2.Instance(
        +    self, "MyFirstEc2Instance",
        +    instance_type=ec2.InstanceType("t2.micro"),
        +    machine_image=ec2.MachineImage.latest_amazon_linux(),
        +    vpc=vpc,
        +    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
        +    security_group=sg,
        +    key_name=key_name
        +)

        ここでは, t2.micro というインスタンスタイプを選択している. さらに, machine_image として, Amazon Linux を選択している (Machine image は OS と似た概念である. Machine image については, Hands-on #2: AWS でディープラーニングを実践 でより詳しく触れる). さらに,上で定義した VPC, SG をこのインスタンスに付与している.

        以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?

        プログラムを実行する

        @@ -35182,13 +35182,13 @@ output = json

        Python の依存ライブラリのインストール

        まずは,Python の依存ライブラリをインストールする.以下では,Python のライブラリを管理するツールとして, venv を使用する.

        まずは, handson/ec2-get-started のディレクトリに移動しよう.

        -
        sh
        $ cd handson/ec2-get-started
        $ cd handson/ec2-get-started
        +
        sh
        $ cd handson/ec2-get-started
        $ cd handson/ec2-get-started

        ディレクトリを移動したら, venv で新しい仮想環境を作成し,インストールを実行する.

        -
        sh
        $ python3 -m venv .env
        -$ source .env/bin/activate
        -$ pip install -r requirements.txt
        $ python3 -m venv .env
        -$ source .env/bin/activate
        -$ pip install -r requirements.txt
        +
        sh
        $ python3 -m venv .env
        +$ source .env/bin/activate
        +$ pip install -r requirements.txt
        $ python3 -m venv .env
        +$ source .env/bin/activate
        +$ pip install -r requirements.txt

        これで Python の環境構築は完了だ.

        venv の簡単な説明は Python クイックガイド に記述してある.

        環境によっては pip ではなく pip3 あるいは python3 -m pip に置き換える必要がある.

        @@ -35198,21 +35198,21 @@ output = json

        SSH 鍵を生成

        EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.

        次の AWS CLI コマンドにより, HirakeGoma という名前のついた鍵を生成する.

        -
        sh
        $ export KEY_NAME="HirakeGoma"
        -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
        $ export KEY_NAME="HirakeGoma"
        -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
        +
        sh
        $ export KEY_NAME="HirakeGoma"
        +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
        $ export KEY_NAME="HirakeGoma"
        +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem

        このコマンドを実行すると,現在のディレクトリに HirakeGoma.pem というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, ~/.ssh/ のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を 400 に設定する.

        -
        sh
        $ mv HirakeGoma.pem ~/.ssh/
        -$ chmod 400 ~/.ssh/HirakeGoma.pem
        $ mv HirakeGoma.pem ~/.ssh/
        -$ chmod 400 ~/.ssh/HirakeGoma.pem
        +
        sh
        $ mv HirakeGoma.pem ~/.ssh/
        +$ chmod 400 ~/.ssh/HirakeGoma.pem
        $ mv HirakeGoma.pem ~/.ssh/
        +$ chmod 400 ~/.ssh/HirakeGoma.pem

        デプロイを実行

        これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. -c key_name="HirakeGoma" というオプションで,先ほど生成した HirakeGoma という名前の鍵を使うよう指定している.

        -
        sh
        $ cdk deploy -c key_name="HirakeGoma"
        $ cdk deploy -c key_name="HirakeGoma"
        +
        sh
        $ cdk deploy -c key_name="HirakeGoma"
        $ cdk deploy -c key_name="HirakeGoma"

        このコマンドを実行すると, VPC, EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に figure_title のような出力が得られるはずである. 出力の中で InstancePublicIp に続く数字が,起動したインスタンスのパブリック IP アドレスである. IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.

        CDKデプロイ実行後の出力

        SSH でログイン

        早速,SSH  で接続してみよう.

        -
        sh
        $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
        $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
        +
        sh
        $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>
        $ ssh -i ~/.ssh/HirakeGoma.pem ec2-user@<IP address>

        -i オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで ec2-user という名前のユーザーが作られているので,それを使用する. 最後に, <IP address> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (12.345.678.9 など).

        ログインに成功すると, figure_title のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが [ec2-user@ip-10-10-1-217 ~]$ のようになっていることを確認しよう.

        SSH で EC2 インスタンスにログイン

        @@ -35220,69 +35220,69 @@ output = json

        起動した EC2 インスタンスで遊んでみる

        せっかく新しいインスタンスを起動したので,少し遊んでみよう.

        ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.

        -
        sh
        $ cat /proc/cpuinfo
        +
        sh
        $ cat /proc/cpuinfo
         
        -processor       : 0
        -vendor_id       : GenuineIntel
        -cpu family      : 6
        -model           : 63
        -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
        -stepping        : 2
        -microcode       : 0x43
        -cpu MHz         : 2400.096
        -cache size      : 30720 KB
        $ cat /proc/cpuinfo
        +processor       : 0
        +vendor_id       : GenuineIntel
        +cpu family      : 6
        +model           : 63
        +model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
        +stepping        : 2
        +microcode       : 0x43
        +cpu MHz         : 2400.096
        +cache size      : 30720 KB
        $ cat /proc/cpuinfo
         
        -processor       : 0
        -vendor_id       : GenuineIntel
        -cpu family      : 6
        -model           : 63
        -model name      : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
        -stepping        : 2
        -microcode       : 0x43
        -cpu MHz         : 2400.096
        -cache size      : 30720 KB
        +processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 63 +model name : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz +stepping : 2 +microcode : 0x43 +cpu MHz : 2400.096 +cache size : 30720 KB

        次に,実行中のプロセスやメモリの消費を見てみよう.

        -
        sh
        $  top -n 1
        +
        sh
        $  top -n 1
         
        -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
        -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
        -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
        -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
        -Swap:        0k total,        0k used,        0k free,   185856k cached
        +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
        +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
        +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
        +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
        +Swap:        0k total,        0k used,        0k free,   185856k cached
         
        -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
        -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
        -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
        -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
        $  top -n 1
        +  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
        +    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
        +    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
        +    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
        $  top -n 1
         
        -top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
        -Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
        -Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
        -Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
        -Swap:        0k total,        0k used,        0k free,   185856k cached
        +top - 09:29:19 up 43 min,  1 user,  load average: 0.00, 0.00, 0.00
        +Tasks:  76 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
        +Cpu(s):  0.3%us,  0.3%sy,  0.1%ni, 98.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.2%st
        +Mem:   1009140k total,   270760k used,   738380k free,    14340k buffers
        +Swap:        0k total,        0k used,        0k free,   185856k cached
         
        -  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
        -    1 root      20   0 19696 2596 2268 S  0.0  0.3   0:01.21 init
        -    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
        -    3 root      20   0     0    0    0 I  0.0  0.0   0:00.00 kworker/0:0
        + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 1 root 20 0 19696 2596 2268 S 0.0 0.3 0:01.21 init + 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd + 3 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0

        t2.micro インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.

        今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.

        -
        sh
        $ sudo yum update -y
        -$ sudo yum install -y python36
        $ sudo yum update -y
        -$ sudo yum install -y python36
        +
        sh
        $ sudo yum update -y
        +$ sudo yum install -y python36
        $ sudo yum update -y
        +$ sudo yum install -y python36

        インストールした Python を起動してみよう.

        -
        sh
        $ python3
        -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
        -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
        -Type "help", "copyright", "credits" or "license" for more information.
        ->>>
        $ python3
        -Python 3.6.10 (default, Feb 10 2020, 19:55:14)
        -[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
        -Type "help", "copyright", "credits" or "license" for more information.
        ->>>
        +
        sh
        $ python3
        +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
        +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
        +Type "help", "copyright", "credits" or "license" for more information.
        +>>>
        $ python3
        +Python 3.6.10 (default, Feb 10 2020, 19:55:14)
        +[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
        +Type "help", "copyright", "credits" or "license" for more information.
        +>>>

        Python のインタープリタが起動した! Ctrl + D あるいは exit() と入力することで,インタープリタを閉じることができる.

        さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) . 次のコマンドでログアウトする.

        -
        sh
        $ exit
        $ exit
        +
        sh
        $ exit
        $ exit

        AWS コンソールから確認

        これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したり,サーバーをシャットダウンするなどの操作は,AWS コンソールから実行することもできる. 軽くこれを紹介しよう.

        まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, Services から EC2 を検索(選択)する. 次に,左のサイドバーの Instances とページをたどる. すると, figure_title のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様に,VPC・SG についてもコンソールから確認できる.

        @@ -35296,16 +35296,16 @@ output = json

        一つ目の方法は,前節の Cloudformation のコンソール画面で, "Delete" ボタンを押すことである (figure_title). すると,スタックの状態が "DELETE_IN_PROGRESS" に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.

        CloudFormationコンソール画面から,スタックを削除

        二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.

        -
        sh
        $ cdk destroy
        $ cdk destroy
        +
        sh
        $ cdk destroy
        $ cdk destroy

        このコマンドを実行すると,スタックの削除が始まる. 削除した後は,VPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.

        スタックの削除は各自で必ず行うこと! 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!

        また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.

        コンソールから実行するには, EC2 の画面に行き,左のサイドバーの Key Pairs を選択する. 鍵の一覧が表示されるので, HirakeGoma とある鍵にチェックを入れ,画面右上の Actions から, Delete を実行する (figure_title).

        EC2でSSH鍵ペアを削除

        コマンドラインから実行するには,次のコマンドを使う.

        -
        sh
        $ aws ec2 delete-key-pair --key-name "HirakeGoma"
        $ aws ec2 delete-key-pair --key-name "HirakeGoma"
        +
        sh
        $ aws ec2 delete-key-pair --key-name "HirakeGoma"
        $ aws ec2 delete-key-pair --key-name "HirakeGoma"

        最後に,ローカルのコンピュータから鍵を削除する.

        -
        sh
        $ rm -f ~/.ssh/HirakeGoma.pem
        $ rm -f ~/.ssh/HirakeGoma.pem
        +
        sh
        $ rm -f ~/.ssh/HirakeGoma.pem
        $ rm -f ~/.ssh/HirakeGoma.pem

        これで,クラウドの片付けもすべて終了だ.

        なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.

        小括

        @@ -35374,85 +35374,85 @@ output = json

      ハンズオンで使用するプログラムのコードをみてみよう handson/mnist/app.py). コードは第一回目とほとんど共通である.変更点のみ解説を行う.

      -
      python
      class Ec2ForDl(core.Stack):
      +
      python
      class Ec2ForDl(core.Stack):
       
      -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
      -        super().__init__(scope, name, **kwargs)
      +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
      +        super().__init__(scope, name, **kwargs)
       
      -        vpc = ec2.Vpc(
      -            self, "Ec2ForDl-Vpc",
      -            max_azs=1,
      -            cidr="10.10.0.0/23",
      -            subnet_configuration=[
      -                ec2.SubnetConfiguration(
      -                    name="public",
      -                    subnet_type=ec2.SubnetType.PUBLIC,
      -                )
      -            ],
      -            nat_gateways=0,
      -        )
      +        vpc = ec2.Vpc(
      +            self, "Ec2ForDl-Vpc",
      +            max_azs=1,
      +            cidr="10.10.0.0/23",
      +            subnet_configuration=[
      +                ec2.SubnetConfiguration(
      +                    name="public",
      +                    subnet_type=ec2.SubnetType.PUBLIC,
      +                )
      +            ],
      +            nat_gateways=0,
      +        )
       
      -        sg = ec2.SecurityGroup(
      -            self, "Ec2ForDl-Sg",
      -            vpc=vpc,
      -            allow_all_outbound=True,
      -        )
      -        sg.add_ingress_rule(
      -            peer=ec2.Peer.any_ipv4(),
      -            connection=ec2.Port.tcp(22),
      -        )
      +        sg = ec2.SecurityGroup(
      +            self, "Ec2ForDl-Sg",
      +            vpc=vpc,
      +            allow_all_outbound=True,
      +        )
      +        sg.add_ingress_rule(
      +            peer=ec2.Peer.any_ipv4(),
      +            connection=ec2.Port.tcp(22),
      +        )
       
      -        host = ec2.Instance(
      -            self, "Ec2ForDl-Instance",
      -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
      -            machine_image=ec2.MachineImage.generic_linux({
      -                "us-east-1": "ami-060f07284bb6f9faf",
      -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
      -            }), #
      -            vpc=vpc,
      -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
      -            security_group=sg,
      -            key_name=key_name
      -        )
      class Ec2ForDl(core.Stack):
      +        host = ec2.Instance(
      +            self, "Ec2ForDl-Instance",
      +            instance_type=ec2.InstanceType("g4dn.xlarge"), #
      +            machine_image=ec2.MachineImage.generic_linux({
      +                "us-east-1": "ami-060f07284bb6f9faf",
      +                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
      +            }), #
      +            vpc=vpc,
      +            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
      +            security_group=sg,
      +            key_name=key_name
      +        )
      class Ec2ForDl(core.Stack):
       
      -    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
      -        super().__init__(scope, name, **kwargs)
      +    def __init__(self, scope: core.App, name: str, key_name: str, **kwargs) -> None:
      +        super().__init__(scope, name, **kwargs)
       
      -        vpc = ec2.Vpc(
      -            self, "Ec2ForDl-Vpc",
      -            max_azs=1,
      -            cidr="10.10.0.0/23",
      -            subnet_configuration=[
      -                ec2.SubnetConfiguration(
      -                    name="public",
      -                    subnet_type=ec2.SubnetType.PUBLIC,
      -                )
      -            ],
      -            nat_gateways=0,
      -        )
      +        vpc = ec2.Vpc(
      +            self, "Ec2ForDl-Vpc",
      +            max_azs=1,
      +            cidr="10.10.0.0/23",
      +            subnet_configuration=[
      +                ec2.SubnetConfiguration(
      +                    name="public",
      +                    subnet_type=ec2.SubnetType.PUBLIC,
      +                )
      +            ],
      +            nat_gateways=0,
      +        )
       
      -        sg = ec2.SecurityGroup(
      -            self, "Ec2ForDl-Sg",
      -            vpc=vpc,
      -            allow_all_outbound=True,
      -        )
      -        sg.add_ingress_rule(
      -            peer=ec2.Peer.any_ipv4(),
      -            connection=ec2.Port.tcp(22),
      -        )
      +        sg = ec2.SecurityGroup(
      +            self, "Ec2ForDl-Sg",
      +            vpc=vpc,
      +            allow_all_outbound=True,
      +        )
      +        sg.add_ingress_rule(
      +            peer=ec2.Peer.any_ipv4(),
      +            connection=ec2.Port.tcp(22),
      +        )
       
      -        host = ec2.Instance(
      -            self, "Ec2ForDl-Instance",
      -            instance_type=ec2.InstanceType("g4dn.xlarge"), #
      -            machine_image=ec2.MachineImage.generic_linux({
      -                "us-east-1": "ami-060f07284bb6f9faf",
      -                "ap-northeast-1": "ami-09c0c16fc46a29ed9"
      -            }), #
      -            vpc=vpc,
      -            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
      -            security_group=sg,
      -            key_name=key_name
      -        )
      + host = ec2.Instance( + self, "Ec2ForDl-Instance", + instance_type=ec2.InstanceType("g4dn.xlarge"), # + machine_image=ec2.MachineImage.generic_linux({ + "us-east-1": "ami-060f07284bb6f9faf", + "ap-northeast-1": "ami-09c0c16fc46a29ed9" + }), # + vpc=vpc, + vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC), + security_group=sg, + key_name=key_name + )
      • ここで, g4dn.xlarge インスタンスタイプを選択している (第一回では, CPU のみの t2.micro だった). g4dn.xlarge のインスタンスタイプは, クラウドで行う科学計算・機械学習 ですでに触れた通り, NVIDIA T4 と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.

        @@ -35467,10 +35467,10 @@ output = json

        AMI (Amazon Machine Image) とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないので,EC2 インスタンスを起動するときには必ずなにかの OS を"インストール"する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば Ubuntu などの Linux 系 OS に加えて,Windows Server を選択することもできる. また, EC2 での使用に最適化された Amazon Linux という AMI も提供されている.

        しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!

        AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (参考). AMI は EC2 のコンソールから検索することが可能である. あるいは,AWS CLI を使って,次のコマンドでリストを取得することができる (参考).

        -
        sh
        $ aws ec2 describe-images --owners amazon
        $ aws ec2 describe-images --owners amazon
        +
        sh
        $ aws ec2 describe-images --owners amazon
        $ aws ec2 describe-images --owners amazon

        ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, DLAMI (Deep Learning AMI) である. DLAMI には TensorFlow, PyTorch などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.

        本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9.この AMI は ap-northeast-1 でしか使用できない点に注意). AWS CLI を使って,この AMI の詳細情報を取得してみよう.

        -
        sh
        $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
        $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
        +
        sh
        $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1
        $ aws ec2 describe-images --owners amazon --image-ids "ami-09c0c16fc46a29ed9" --region ap-northeast-1

        AMI ID = ami-09c0c16fc46a29ed9 の詳細情報

        figure_title のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.

        DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: 公式ドキュメンテーション "What Is the AWS Deep Learning AMI?").

        @@ -35479,43 +35479,43 @@ output = json

        スタックのデプロイ

        スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

        デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

        -
        sh
        # プロジェクトのディレクトリに移動
        -$ cd handson/mnist
        +
        sh
        # プロジェクトのディレクトリに移動
        +$ cd handson/mnist
         
        -# venv を作成し,依存ライブラリのインストールを行う
        -$ python3 -m venv .env
        -$ source .env/bin/activate
        -$ pip install -r requirements.txt
        +# venv を作成し,依存ライブラリのインストールを行う
        +$ python3 -m venv .env
        +$ source .env/bin/activate
        +$ pip install -r requirements.txt
         
        -# SSH鍵を生成
        -$ export KEY_NAME="HirakeGoma"
        -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
        -$ mv HirakeGoma.pem ~/.ssh/
        -$ chmod 400 ~/.ssh/HirakeGoma.pem
        +# SSH鍵を生成
        +$ export KEY_NAME="HirakeGoma"
        +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
        +$ mv HirakeGoma.pem ~/.ssh/
        +$ chmod 400 ~/.ssh/HirakeGoma.pem
         
        -# デプロイを実行
        -$ cdk deploy -c key_name="HirakeGoma"
        # プロジェクトのディレクトリに移動
        -$ cd handson/mnist
        +# デプロイを実行
        +$ cdk deploy -c key_name="HirakeGoma"
        # プロジェクトのディレクトリに移動
        +$ cd handson/mnist
         
        -# venv を作成し,依存ライブラリのインストールを行う
        -$ python3 -m venv .env
        -$ source .env/bin/activate
        -$ pip install -r requirements.txt
        +# venv を作成し,依存ライブラリのインストールを行う
        +$ python3 -m venv .env
        +$ source .env/bin/activate
        +$ pip install -r requirements.txt
         
        -# SSH鍵を生成
        -$ export KEY_NAME="HirakeGoma"
        -$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
        -$ mv HirakeGoma.pem ~/.ssh/
        -$ chmod 400 ~/.ssh/HirakeGoma.pem
        +# SSH鍵を生成
        +$ export KEY_NAME="HirakeGoma"
        +$ aws ec2 create-key-pair --key-name ${KEY_NAME} --query 'KeyMaterial' --output text > ${KEY_NAME}.pem
        +$ mv HirakeGoma.pem ~/.ssh/
        +$ chmod 400 ~/.ssh/HirakeGoma.pem
         
        -# デプロイを実行
        -$ cdk deploy -c key_name="HirakeGoma"
        +# デプロイを実行 +$ cdk deploy -c key_name="HirakeGoma"

        ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.

        デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.AWS により割り振られた IP アドレス (InstancePublicIp に続く文字列) をメモしておこう.

        CDKデプロイ実行後の出力

        ログイン

        早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,ポートフォワーディング (port forwarding) のオプション (-L) をつけてログインする.

        -
        sh
        $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
        $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
        +
        sh
        $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>
        $ ssh -i ~/.ssh/HirakeGoma.pem -L localhost:8931:localhost:8888 ec2-user@<IP address>

        ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの -L localhost:8931:localhost:8888 は,自分のローカルマシンの localhost:8931 へのアクセスを,リモートサーバーの localhost:8888 のアドレスに転送せよ,という意味である (: につづく数字は TCP/IP ポートの番号を意味している). リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの localhost:8931 にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (figure_title). このような SSH による接続方式をトンネル接続とよぶ.

        SSH のポートフォワーディングによる Jupyter Notebook へのアクセス

        ポートフォワーディングのオプションで,ポートの番号 (:8931, :8888 など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがって,リモート側のポート番号は,8888 を使うのがよい.

        @@ -35524,7 +35524,7 @@ output = json

        SSH によるログインは, Docker の外 (すなわちクライアントマシン本体) から行わなければならない. なぜなら,Jupyter を開くウェブブラウザは Docker の外にあるからである.

        その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, cat ~/.ssh/HirakeGoma と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは -v オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは Docker 公式ドキュメンテーション "Use volumes" を参照).

        SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.

        -
        sh
        $ nvidia-smi
        $ nvidia-smi
        +
        sh
        $ nvidia-smi
        $ nvidia-smi

        figure_title のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他,GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.

        nvidia-smi の出力

        Jupyter Notebook の起動

        @@ -35532,9 +35532,9 @@ output = json

        Jupyter Notebook の画面

        このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.

        早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.

        -
        sh
        $ cd ~ # go to home directory
        -$ jupyter notebook
        $ cd ~ # go to home directory
        -$ jupyter notebook
        +
        sh
        $ cd ~ # go to home directory
        +$ jupyter notebook
        $ cd ~ # go to home directory
        +$ jupyter notebook

        このコマンドを実行すると, figure_title のような出力が確認できるだろう. この出力から,Jupyter のサーバーが EC2 インスタンスの localhost:8888 というアドレスに起動していることがわかる. また, localhost:8888 に続く ?token=XXXX は,アクセスに使うための一時的なトークンである.

        Jupyter Notebook サーバーを起動

        Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.

        @@ -35570,31 +35570,31 @@ output = json

        ここでは,次のようなプログラムを書いて,実行していく. (figure_title).

        PyTorch始めの一歩

        まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.

        -
        python
        import torch
        -print("Is CUDA ready?", torch.cuda.is_available())
        import torch
        -print("Is CUDA ready?", torch.cuda.is_available())
        +
        python
        import torch
        +print("Is CUDA ready?", torch.cuda.is_available())
        import torch
        +print("Is CUDA ready?", torch.cuda.is_available())

        出力:

        Is CUDA ready? True</programlisting>

        次に,3x3 のランダムな行列を CPU 上に作ってみよう.

        -
        python
        x = torch.rand(3,3)
        -print(x)
        x = torch.rand(3,3)
        -print(x)
        +
        python
        x = torch.rand(3,3)
        +print(x)
        x = torch.rand(3,3)
        +print(x)

        出力:

        tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])</programlisting>

        次に,行列を GPU 上に作成する.

        -
        python
        y = torch.ones_like(x, device="cuda")
        -x = x.to("cuda")
        y = torch.ones_like(x, device="cuda")
        -x = x.to("cuda")
        +
        python
        y = torch.ones_like(x, device="cuda")
        +x = x.to("cuda")
        y = torch.ones_like(x, device="cuda")
        +x = x.to("cuda")

        そして,行列 xy の加算を,GPU 上で実行する

        -
        python
        z = x + y
        -print(z)
        z = x + y
        -print(z)
        +
        python
        z = x + y
        +print(z)
        z = x + y
        +print(z)

        出力:

        tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device='cuda:0')</programlisting>

        最後に, GPU 上にある行列を, CPU に戻す.

        -
        python
        z = z.to("cpu")
        -print(z)
        z = z.to("cpu")
        -print(z)
        +
        python
        z = z.to("cpu")
        +print(z)
        z = z.to("cpu")
        +print(z)

        出力:

        tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])</programlisting>

        以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.

        @@ -35602,33 +35602,33 @@ output = json

        しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.

        実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する %time マジックコマンドを利用する.

        まずは CPU を使用して,10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.

        -
        python
        s = 10000
        -device = "cpu"
        -x = torch.rand(s, s, device=device, dtype=torch.float32)
        -y = torch.rand(s, s, device=device, dtype=torch.float32)
        +
        python
        s = 10000
        +device = "cpu"
        +x = torch.rand(s, s, device=device, dtype=torch.float32)
        +y = torch.rand(s, s, device=device, dtype=torch.float32)
         
        -%time z = torch.matmul(x,y)
        s = 10000
        -device = "cpu"
        -x = torch.rand(s, s, device=device, dtype=torch.float32)
        -y = torch.rand(s, s, device=device, dtype=torch.float32)
        +%time z = torch.matmul(x,y)
        s = 10000
        +device = "cpu"
        +x = torch.rand(s, s, device=device, dtype=torch.float32)
        +y = torch.rand(s, s, device=device, dtype=torch.float32)
         
        -%time z = torch.matmul(x,y)
        +%time z = torch.matmul(x,y)

        出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意).

        CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s</programlisting>

        次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.

        -
        python
        s = 10000
        -device = "cuda"
        -x = torch.rand(s, s, device=device, dtype=torch.float32)
        -y = torch.rand(s, s, device=device, dtype=torch.float32)
        -torch.cuda.synchronize()
        +
        python
        s = 10000
        +device = "cuda"
        +x = torch.rand(s, s, device=device, dtype=torch.float32)
        +y = torch.rand(s, s, device=device, dtype=torch.float32)
        +torch.cuda.synchronize()
         
        -%time z = torch.matmul(x,y); torch.cuda.synchronize()
        s = 10000
        -device = "cuda"
        -x = torch.rand(s, s, device=device, dtype=torch.float32)
        -y = torch.rand(s, s, device=device, dtype=torch.float32)
        -torch.cuda.synchronize()
        +%time z = torch.matmul(x,y); torch.cuda.synchronize()
        s = 10000
        +device = "cuda"
        +x = torch.rand(s, s, device=device, dtype=torch.float32)
        +y = torch.rand(s, s, device=device, dtype=torch.float32)
        +torch.cuda.synchronize()
         
        -%time z = torch.matmul(x,y); torch.cuda.synchronize()
        +%time z = torch.matmul(x,y); torch.cuda.synchronize()

        出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!

        CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms</programlisting>

        PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, torch.cuda.synchronize() というステートメントを埋め込んである.

        @@ -35643,140 +35643,140 @@ output = json

         をアップロード

        simple_mnist.py をアップロードできたら,次に新しい notebook を作成しよう. "conda_pytorch_p36" の環境を選択することを忘れずに.

        新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.

        -
        python
        import torch
        -import torch.optim as optim
        -import torchvision
        -from torchvision import datasets, transforms
        -from matplotlib import pyplot as plt
        +
        python
        import torch
        +import torch.optim as optim
        +import torchvision
        +from torchvision import datasets, transforms
        +from matplotlib import pyplot as plt
         
        -# custom functions and classes
        -from simple_mnist import Model, train, evaluate
        import torch
        -import torch.optim as optim
        -import torchvision
        -from torchvision import datasets, transforms
        -from matplotlib import pyplot as plt
        +# custom functions and classes
        +from simple_mnist import Model, train, evaluate
        import torch
        +import torch.optim as optim
        +import torchvision
        +from torchvision import datasets, transforms
        +from matplotlib import pyplot as plt
         
        -# custom functions and classes
        -from simple_mnist import Model, train, evaluate
        +# custom functions and classes +from simple_mnist import Model, train, evaluate

        torchvision パッケージには,MNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (Model, train, evaluate) のインポートを行っている.

        次に,MNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.

        -
        python
        transf = transforms.Compose([transforms.ToTensor(),
        -                             transforms.Normalize((0.1307,), (0.3081,))])
        +
        python
        transf = transforms.Compose([transforms.ToTensor(),
        +                             transforms.Normalize((0.1307,), (0.3081,))])
         
        -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
        -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
        +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
        +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
         
        -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
        -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
        transf = transforms.Compose([transforms.ToTensor(),
        -                             transforms.Normalize((0.1307,), (0.3081,))])
        +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
        +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
        transf = transforms.Compose([transforms.ToTensor(),
        +                             transforms.Normalize((0.1307,), (0.3081,))])
         
        -trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
        -trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
        +trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
        +trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
         
        -testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
        -testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)
        +testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf) +testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

        今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. figure_title のような出力が得られるはずである.

        -
        python
        examples = iter(testloader)
        -example_data, example_targets = examples.next()
        +
        python
        examples = iter(testloader)
        +example_data, example_targets = examples.next()
         
        -print("Example data size:", example_data.shape)
        +print("Example data size:", example_data.shape)
         
        -fig = plt.figure(figsize=(10,4))
        -for i in range(10):
        -    plt.subplot(2,5,i+1)
        -    plt.tight_layout()
        -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
        -    plt.title("Ground Truth: {}".format(example_targets[i]))
        -    plt.xticks([])
        -    plt.yticks([])
        -plt.show()
        examples = iter(testloader)
        -example_data, example_targets = examples.next()
        +fig = plt.figure(figsize=(10,4))
        +for i in range(10):
        +    plt.subplot(2,5,i+1)
        +    plt.tight_layout()
        +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
        +    plt.title("Ground Truth: {}".format(example_targets[i]))
        +    plt.xticks([])
        +    plt.yticks([])
        +plt.show()
        examples = iter(testloader)
        +example_data, example_targets = examples.next()
         
        -print("Example data size:", example_data.shape)
        +print("Example data size:", example_data.shape)
         
        -fig = plt.figure(figsize=(10,4))
        -for i in range(10):
        -    plt.subplot(2,5,i+1)
        -    plt.tight_layout()
        -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
        -    plt.title("Ground Truth: {}".format(example_targets[i]))
        -    plt.xticks([])
        -    plt.yticks([])
        -plt.show()
        +fig = plt.figure(figsize=(10,4)) +for i in range(10): + plt.subplot(2,5,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], cmap='gray', interpolation='none') + plt.title("Ground Truth: {}".format(example_targets[i])) + plt.xticks([]) + plt.yticks([]) +plt.show()

        MNIST の手書き数字画像とその教師ラベル

        次に, CNN のモデルを定義する.

        -
        python
        model = Model()
        -model.to("cuda") # load to GPU
        model = Model()
        -model.to("cuda") # load to GPU
        +
        python
        model = Model()
        +model.to("cuda") # load to GPU
        model = Model()
        +model.to("cuda") # load to GPU

        今回使う Modelsimple_mnist.py の中で定義されている. このモデルは,figure_title に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.

        本ハンズオンで使用するニューラルネットの構造.

        続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, 確率的勾配降下法 (Stochastic Gradient Descent; SGD) を使用している.

        -
        python
        optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
        optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
        +
        python
        optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
        optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

        これで,準備が整った. CNN の学習ループを開始しよう!

        -
        python
        train_losses = []
        -for epoch in range(5):
        -    losses = train(model, trainloader, optimizer, epoch)
        -    train_losses = train_losses + losses
        -    test_loss, test_accuracy = evaluate(model, testloader)
        -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
        +
        python
        train_losses = []
        +for epoch in range(5):
        +    losses = train(model, trainloader, optimizer, epoch)
        +    train_losses = train_losses + losses
        +    test_loss, test_accuracy = evaluate(model, testloader)
        +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
         
        -plt.figure(figsize=(7,5))
        -plt.plot(train_losses)
        -plt.xlabel("Iterations")
        -plt.ylabel("Train loss")
        -plt.show()
        train_losses = []
        -for epoch in range(5):
        -    losses = train(model, trainloader, optimizer, epoch)
        -    train_losses = train_losses + losses
        -    test_loss, test_accuracy = evaluate(model, testloader)
        -    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
        +plt.figure(figsize=(7,5))
        +plt.plot(train_losses)
        +plt.xlabel("Iterations")
        +plt.ylabel("Train loss")
        +plt.show()
        train_losses = []
        +for epoch in range(5):
        +    losses = train(model, trainloader, optimizer, epoch)
        +    train_losses = train_losses + losses
        +    test_loss, test_accuracy = evaluate(model, testloader)
        +    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")
         
        -plt.figure(figsize=(7,5))
        -plt.plot(train_losses)
        -plt.xlabel("Iterations")
        -plt.ylabel("Train loss")
        -plt.show()
        +plt.figure(figsize=(7,5)) +plt.plot(train_losses) +plt.xlabel("Iterations") +plt.ylabel("Train loss") +plt.show()

        ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.

        出力として, figure_title のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.

        学習の進行に対する Train loss の変化

        出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (figure_title).

        学習したCNNのテストデータに対するスコア (5エポック後)

        学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, figure_title のような出力が得られるだろう. この図で,下段右から二番目は,"1"に近い見た目をしているが,きちんと"9"と推論できている. なかなか賢い CNN を作り出すことができたようだ!

        -
        python
        model.eval()
        +
        python
        model.eval()
         
        -with torch.no_grad():
        -    output = model(example_data.to("cuda"))
        +with torch.no_grad():
        +    output = model(example_data.to("cuda"))
         
        -fig = plt.figure(figsize=(10,4))
        -for i in range(10):
        -    plt.subplot(2,5,i+1)
        -    plt.tight_layout()
        -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
        -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
        -    plt.xticks([])
        -    plt.yticks([])
        -plt.show()
        model.eval()
        +fig = plt.figure(figsize=(10,4))
        +for i in range(10):
        +    plt.subplot(2,5,i+1)
        +    plt.tight_layout()
        +    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
        +    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
        +    plt.xticks([])
        +    plt.yticks([])
        +plt.show()
        model.eval()
         
        -with torch.no_grad():
        -    output = model(example_data.to("cuda"))
        +with torch.no_grad():
        +    output = model(example_data.to("cuda"))
         
        -fig = plt.figure(figsize=(10,4))
        -for i in range(10):
        -    plt.subplot(2,5,i+1)
        -    plt.tight_layout()
        -    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
        -    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
        -    plt.xticks([])
        -    plt.yticks([])
        -plt.show()
        +fig = plt.figure(figsize=(10,4)) +for i in range(10): + plt.subplot(2,5,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], cmap='gray', interpolation='none') + plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item())) + plt.xticks([]) + plt.yticks([]) +plt.show()

        学習した CNN による,MNIST画像の推論結果

        最後に,学習したニューラルネットワークのパラメータを mnist_cnn.pt というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.

        -
        python
        torch.save(model.state_dict(), "mnist_cnn.pt")
        torch.save(model.state_dict(), "mnist_cnn.pt")
        +
        python
        torch.save(model.state_dict(), "mnist_cnn.pt")
        torch.save(model.state_dict(), "mnist_cnn.pt")

        以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.

        スタックの削除

        これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.

        ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は スタックを削除 参照).

        -
        sh
        $ cdk destroy
        $ cdk destroy
        +
        sh
        $ cdk destroy
        $ cdk destroy

        スタックの削除は各自で必ず行うこと! 行わなかった場合,EC2 インスタンスの料金が発生し続けることになる! g4dn.xlarge は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!

        AWS のバジェットアラート

        AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は AWS の公式ブログ "Getting Started with AWS Budgets" を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.

        @@ -35815,92 +35815,92 @@ output = json

        イメージをダウンロード

        パッケージ化された Docker の仮想環境 (= イメージ (Image)) は, Docker Hub からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.

        たとえば, Ubuntu のイメージは Ubuntu の公式リポジトリ で公開されており, pull コマンドを使うことでローカルにダウンロードすることができる.

        -
        sh
        $ docker pull ubuntu:18.04
        $ docker pull ubuntu:18.04
        +
        sh
        $ docker pull ubuntu:18.04
        $ docker pull ubuntu:18.04

        ここで,イメージ名の : (コロン) 以降に続く文字列を タグ (tag) と呼び,主にバージョンを指定するなどの目的で使われる.

        pull コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, myregistry.local:5000/testing/test-image のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.

        コンテナを起動

        Pull してきたイメージを起動するには, run コマンドを使う.

        -
        sh
        $ docker run -it ubuntu:18.04
        $ docker run -it ubuntu:18.04
        +
        sh
        $ docker run -it ubuntu:18.04
        $ docker run -it ubuntu:18.04

        ここで, -it とは,インタラクティブな shell のセッションを開始するために必要なオプションである.

        このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (figure_title). このように起動状態にある計算環境 (ランタイム) のことを Container (コンテナ) とよぶ.

        Docker を使って ubuntu:18.04 イメージを起動

        ここで使用した ubuntu:18.04 のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, Hands-on #2: AWS でディープラーニングを実践 でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは PyTorch 公式の Docker Hub リポジトリ で公開されている.

        これを起動してみよう.

        -
        sh
        $ docker run -it pytorch/pytorch
        $ docker run -it pytorch/pytorch
        +
        sh
        $ docker run -it pytorch/pytorch
        $ docker run -it pytorch/pytorch

        docker run を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.

        pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.

        -
        sh
        $ python3
        -Python 3.7.7 (default, May  7 2020, 21:25:33)
        -[GCC 7.3.0] :: Anaconda, Inc. on linux
        -Type "help", "copyright", "credits" or "license" for more information.
        ->>> import torch
        ->>> torch.cuda.is_available()
        -False
        $ python3
        -Python 3.7.7 (default, May  7 2020, 21:25:33)
        -[GCC 7.3.0] :: Anaconda, Inc. on linux
        -Type "help", "copyright", "credits" or "license" for more information.
        ->>> import torch
        ->>> torch.cuda.is_available()
        -False
        +
        sh
        $ python3
        +Python 3.7.7 (default, May  7 2020, 21:25:33)
        +[GCC 7.3.0] :: Anaconda, Inc. on linux
        +Type "help", "copyright", "credits" or "license" for more information.
        +>>> import torch
        +>>> torch.cuda.is_available()
        +False
        $ python3
        +Python 3.7.7 (default, May  7 2020, 21:25:33)
        +[GCC 7.3.0] :: Anaconda, Inc. on linux
        +Type "help", "copyright", "credits" or "license" for more information.
        +>>> import torch
        +>>> torch.cuda.is_available()
        +False

        このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる.

        自分だけのイメージを作る

        自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.

        たとえば, 本書のハンズオン実行用に提供している docker イメージ には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.

        カスタムの docker イメージを作るには, Dockerfile という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.

        具体例として,本書で提供している Docker イメージのレシピを見てみよう (docker/Dockerfile).

        -
        python
        FROM node:12
        -LABEL maintainer="Tomoyuki Mano"
        +
        python
        FROM node:12
        +LABEL maintainer="Tomoyuki Mano"
         
        -RUN apt-get update \
        -    && apt-get install nano
        +RUN apt-get update \
        +    && apt-get install nano
         
        -#
        -RUN cd /opt \
        -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
        -    && tar -xzf Python-3.7.6.tgz \
        -    && cd Python-3.7.6 \
        -    && ./configure --enable-optimizations \
        -    && make install
        +#
        +RUN cd /opt \
        +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
        +    && tar -xzf Python-3.7.6.tgz \
        +    && cd Python-3.7.6 \
        +    && ./configure --enable-optimizations \
        +    && make install
         
        -RUN cd /opt \
        -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
        -    && unzip awscliv2.zip \
        -    && ./aws/install
        +RUN cd /opt \
        +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
        +    && unzip awscliv2.zip \
        +    && ./aws/install
         
        -#
        -RUN npm install -g aws-cdk@1.100
        +#
        +RUN npm install -g aws-cdk@1.100
         
        -# clean up unnecessary files
        -RUN rm -rf /opt/*
        +# clean up unnecessary files
        +RUN rm -rf /opt/*
         
        -# copy hands-on source code in /root/
        -COPY handson/ /root/handson
        FROM node:12
        -LABEL maintainer="Tomoyuki Mano"
        +# copy hands-on source code in /root/
        +COPY handson/ /root/handson
        FROM node:12
        +LABEL maintainer="Tomoyuki Mano"
         
        -RUN apt-get update \
        -    && apt-get install nano
        +RUN apt-get update \
        +    && apt-get install nano
         
        -#
        -RUN cd /opt \
        -    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
        -    && tar -xzf Python-3.7.6.tgz \
        -    && cd Python-3.7.6 \
        -    && ./configure --enable-optimizations \
        -    && make install
        +#
        +RUN cd /opt \
        +    && curl -q "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" -o Python-3.7.6.tgz \
        +    && tar -xzf Python-3.7.6.tgz \
        +    && cd Python-3.7.6 \
        +    && ./configure --enable-optimizations \
        +    && make install
         
        -RUN cd /opt \
        -    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
        -    && unzip awscliv2.zip \
        -    && ./aws/install
        +RUN cd /opt \
        +    && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
        +    && unzip awscliv2.zip \
        +    && ./aws/install
         
        -#
        -RUN npm install -g aws-cdk@1.100
        +#
        +RUN npm install -g aws-cdk@1.100
         
        -# clean up unnecessary files
        -RUN rm -rf /opt/*
        +# clean up unnecessary files
        +RUN rm -rf /opt/*
         
        -# copy hands-on source code in /root/
        -COPY handson/ /root/handson
        +# copy hands-on source code in /root/ +COPY handson/ /root/handson

        Dockerfile の中身の説明は詳しくは行わないが,たとえば上のコードで <1> で示したところは, Python 3.7 のインストールを実行している. また, <2> で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.

        "ぼくの環境ではそのプログラム走ったのにな…" というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.

        コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いが,Docker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.

        @@ -35934,35 +35934,35 @@ output = json

        このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.

        Transformer を用いた question-answering プログラム

        このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.

        -
        txt
        context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
        -
        -question: In what year did Einstein win the Nobel prize?
        context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
        -
        -question: In what year did Einstein win the Nobel prize?
        +
        txt
        context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
        +
        +question: In what year did Einstein win the Nobel prize?
        context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.
        +
        +question: In what year did Einstein win the Nobel prize?

        今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.

        -
        sh
        answer: 1921
        answer: 1921
        +
        sh
        answer: 1921
        answer: 1921

        人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.

        今回は, huggingface/transformers で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは Transformer とよばれるモデルを使った自然言語処理に支えられえている (figure_title). このプログラムを, Docker にパッケージしたものが 著者の Docker Hub リポジトリ に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.

        Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)

        なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.

        次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.

        -
        sh
        $ docker pull tomomano/qabot:latest
        $ docker pull tomomano/qabot:latest
        +
        sh
        $ docker pull tomomano/qabot:latest
        $ docker pull tomomano/qabot:latest

        pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.

        -
        sh
        $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
        -$ question="In what year did Einstein win the Nobel prize ?"
        $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
        -$ question="In what year did Einstein win the Nobel prize ?"
        +
        sh
        $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
        +$ question="In what year did Einstein win the Nobel prize ?"
        $ context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."
        +$ question="In what year did Einstein win the Nobel prize ?"

        そうしたら,次のコマンドによってコンテナを実行する.

        -
        sh
        $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
        $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
        +
        sh
        $ docker run tomomano/qabot "${context}" "${question}" foo --no_save
        $ docker run tomomano/qabot "${context}" "${question}" foo --no_save

        今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.

        このコマンドを実行すると,次のような出力が得られるはずである.

        -
        sh
        {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
        {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
        +
        sh
        {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}
        {'score': 0.9881729286683587, 'start': 437, 'end': 441, 'answer': '1921'}

        "score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.

        もう少し難しい質問を投げかけてみよう.

        -
        sh
        $ question="Why did Einstein win the Nobel prize ?"
        -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
        $ question="Why did Einstein win the Nobel prize ?"
        -$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
        +
        sh
        $ question="Why did Einstein win the Nobel prize ?"
        +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save
        $ question="Why did Einstein win the Nobel prize ?"
        +$ docker run tomomano/qabot "${context}" "${question}" foo --no_save

        出力:

        -
        sh
        {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
        {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
        +
        sh
        {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}
        {'score': 0.5235594527494207, 'start': 470, 'end': 506, 'answer': 'his services to theoretical physics,'}

        今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.

        このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.

        今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, 原著論文 を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは 公式ドキュメンテーション を参照のこと.

        @@ -35998,109 +35998,109 @@ output = json

      それでは,プログラムのソースコードを見てみよう (handson/qa-bot/app.py).

      -
      sh
      class EcsClusterQaBot(core.Stack):
      +
      sh
      class EcsClusterQaBot(core.Stack):
       
      -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
      -        super().__init__(scope, name, **kwargs)
      +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
      +        super().__init__(scope, name, **kwargs)
       
      -        #
      -        # dynamoDB table to store questions and answers
      -        table = dynamodb.Table(
      -            self, "EcsClusterQaBot-Table",
      -            partition_key=dynamodb.Attribute(
      -                name="item_id", type=dynamodb.AttributeType.STRING
      -            ),
      -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
      -            removal_policy=core.RemovalPolicy.DESTROY
      -        )
      +        #
      +        # dynamoDB table to store questions and answers
      +        table = dynamodb.Table(
      +            self, "EcsClusterQaBot-Table",
      +            partition_key=dynamodb.Attribute(
      +                name="item_id", type=dynamodb.AttributeType.STRING
      +            ),
      +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
      +            removal_policy=core.RemovalPolicy.DESTROY
      +        )
       
      -        #
      -        vpc = ec2.Vpc(
      -            self, "EcsClusterQaBot-Vpc",
      -            max_azs=1,
      -        )
      +        #
      +        vpc = ec2.Vpc(
      +            self, "EcsClusterQaBot-Vpc",
      +            max_azs=1,
      +        )
       
      -        #
      -        cluster = ecs.Cluster(
      -            self, "EcsClusterQaBot-Cluster",
      -            vpc=vpc,
      -        )
      +        #
      +        cluster = ecs.Cluster(
      +            self, "EcsClusterQaBot-Cluster",
      +            vpc=vpc,
      +        )
       
      -        #
      -        taskdef = ecs.FargateTaskDefinition(
      -            self, "EcsClusterQaBot-TaskDef",
      -            cpu=1024, # 1 CPU
      -            memory_limit_mib=4096, # 4GB RAM
      -        )
      +        #
      +        taskdef = ecs.FargateTaskDefinition(
      +            self, "EcsClusterQaBot-TaskDef",
      +            cpu=1024, # 1 CPU
      +            memory_limit_mib=4096, # 4GB RAM
      +        )
       
      -        # grant permissions
      -        table.grant_read_write_data(taskdef.task_role)
      -        taskdef.add_to_task_role_policy(
      -            iam.PolicyStatement(
      -                effect=iam.Effect.ALLOW,
      -                resources=["*"],
      -                actions=["ssm:GetParameter"]
      -            )
      -        )
      +        # grant permissions
      +        table.grant_read_write_data(taskdef.task_role)
      +        taskdef.add_to_task_role_policy(
      +            iam.PolicyStatement(
      +                effect=iam.Effect.ALLOW,
      +                resources=["*"],
      +                actions=["ssm:GetParameter"]
      +            )
      +        )
       
      -        #
      -        container = taskdef.add_container(
      -            "EcsClusterQaBot-Container",
      -            image=ecs.ContainerImage.from_registry(
      -                "tomomano/qabot:latest"
      -            ),
      -        )
      class EcsClusterQaBot(core.Stack):
      +        #
      +        container = taskdef.add_container(
      +            "EcsClusterQaBot-Container",
      +            image=ecs.ContainerImage.from_registry(
      +                "tomomano/qabot:latest"
      +            ),
      +        )
      class EcsClusterQaBot(core.Stack):
       
      -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
      -        super().__init__(scope, name, **kwargs)
      +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
      +        super().__init__(scope, name, **kwargs)
       
      -        #
      -        # dynamoDB table to store questions and answers
      -        table = dynamodb.Table(
      -            self, "EcsClusterQaBot-Table",
      -            partition_key=dynamodb.Attribute(
      -                name="item_id", type=dynamodb.AttributeType.STRING
      -            ),
      -            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
      -            removal_policy=core.RemovalPolicy.DESTROY
      -        )
      +        #
      +        # dynamoDB table to store questions and answers
      +        table = dynamodb.Table(
      +            self, "EcsClusterQaBot-Table",
      +            partition_key=dynamodb.Attribute(
      +                name="item_id", type=dynamodb.AttributeType.STRING
      +            ),
      +            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
      +            removal_policy=core.RemovalPolicy.DESTROY
      +        )
       
      -        #
      -        vpc = ec2.Vpc(
      -            self, "EcsClusterQaBot-Vpc",
      -            max_azs=1,
      -        )
      +        #
      +        vpc = ec2.Vpc(
      +            self, "EcsClusterQaBot-Vpc",
      +            max_azs=1,
      +        )
       
      -        #
      -        cluster = ecs.Cluster(
      -            self, "EcsClusterQaBot-Cluster",
      -            vpc=vpc,
      -        )
      +        #
      +        cluster = ecs.Cluster(
      +            self, "EcsClusterQaBot-Cluster",
      +            vpc=vpc,
      +        )
       
      -        #
      -        taskdef = ecs.FargateTaskDefinition(
      -            self, "EcsClusterQaBot-TaskDef",
      -            cpu=1024, # 1 CPU
      -            memory_limit_mib=4096, # 4GB RAM
      -        )
      +        #
      +        taskdef = ecs.FargateTaskDefinition(
      +            self, "EcsClusterQaBot-TaskDef",
      +            cpu=1024, # 1 CPU
      +            memory_limit_mib=4096, # 4GB RAM
      +        )
       
      -        # grant permissions
      -        table.grant_read_write_data(taskdef.task_role)
      -        taskdef.add_to_task_role_policy(
      -            iam.PolicyStatement(
      -                effect=iam.Effect.ALLOW,
      -                resources=["*"],
      -                actions=["ssm:GetParameter"]
      -            )
      -        )
      +        # grant permissions
      +        table.grant_read_write_data(taskdef.task_role)
      +        taskdef.add_to_task_role_policy(
      +            iam.PolicyStatement(
      +                effect=iam.Effect.ALLOW,
      +                resources=["*"],
      +                actions=["ssm:GetParameter"]
      +            )
      +        )
       
      -        #
      -        container = taskdef.add_container(
      -            "EcsClusterQaBot-Container",
      -            image=ecs.ContainerImage.from_registry(
      -                "tomomano/qabot:latest"
      -            ),
      -        )
      + # + container = taskdef.add_container( + "EcsClusterQaBot-Container", + image=ecs.ContainerImage.from_registry( + "tomomano/qabot:latest" + ), + )
      • ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.

        @@ -36120,39 +36120,39 @@ output = json

      ECS と Fargate

      ECS と Fargate の部分について,コードをくわしく見てみよう.

      -
      sh
      cluster = ecs.Cluster(
      -    self, "EcsClusterQaBot-Cluster",
      -    vpc=vpc,
      -)
      +
      sh
      cluster = ecs.Cluster(
      +    self, "EcsClusterQaBot-Cluster",
      +    vpc=vpc,
      +)
       
      -taskdef = ecs.FargateTaskDefinition(
      -    self, "EcsClusterQaBot-TaskDef",
      -    cpu=1024, # 1 CPU
      -    memory_limit_mib=4096, # 4GB RAM
      -)
      +taskdef = ecs.FargateTaskDefinition(
      +    self, "EcsClusterQaBot-TaskDef",
      +    cpu=1024, # 1 CPU
      +    memory_limit_mib=4096, # 4GB RAM
      +)
       
      -container = taskdef.add_container(
      -    "EcsClusterQaBot-Container",
      -    image=ecs.ContainerImage.from_registry(
      -        "tomomano/qabot:latest"
      -    ),
      -)
      cluster = ecs.Cluster(
      -    self, "EcsClusterQaBot-Cluster",
      -    vpc=vpc,
      -)
      +container = taskdef.add_container(
      +    "EcsClusterQaBot-Container",
      +    image=ecs.ContainerImage.from_registry(
      +        "tomomano/qabot:latest"
      +    ),
      +)
      cluster = ecs.Cluster(
      +    self, "EcsClusterQaBot-Cluster",
      +    vpc=vpc,
      +)
       
      -taskdef = ecs.FargateTaskDefinition(
      -    self, "EcsClusterQaBot-TaskDef",
      -    cpu=1024, # 1 CPU
      -    memory_limit_mib=4096, # 4GB RAM
      -)
      +taskdef = ecs.FargateTaskDefinition(
      +    self, "EcsClusterQaBot-TaskDef",
      +    cpu=1024, # 1 CPU
      +    memory_limit_mib=4096, # 4GB RAM
      +)
       
      -container = taskdef.add_container(
      -    "EcsClusterQaBot-Container",
      -    image=ecs.ContainerImage.from_registry(
      -        "tomomano/qabot:latest"
      -    ),
      -)
      +container = taskdef.add_container( + "EcsClusterQaBot-Container", + image=ecs.ContainerImage.from_registry( + "tomomano/qabot:latest" + ), +)

      cluster = の箇所で,空の ECS クラスターを定義している.

      次に, taskdef=ecs.FargateTaskDefinition の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.

      最後に, container = の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.

      @@ -36162,25 +36162,25 @@ output = json

      スタックのデプロイ

      スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

      デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

      -
      sh
      # プロジェクトのディレクトリに移動
      -$ cd handson/qa-bot
      +
      sh
      # プロジェクトのディレクトリに移動
      +$ cd handson/qa-bot
       
      -# venv を作成し,依存ライブラリのインストールを行う
      -$ python3 -m venv .env
      -$ source .env/bin/activate
      -$ pip install -r requirements.txt
      +# venv を作成し,依存ライブラリのインストールを行う
      +$ python3 -m venv .env
      +$ source .env/bin/activate
      +$ pip install -r requirements.txt
       
      -# デプロイを実行
      -$ cdk deploy
      # プロジェクトのディレクトリに移動
      -$ cd handson/qa-bot
      +# デプロイを実行
      +$ cdk deploy
      # プロジェクトのディレクトリに移動
      +$ cd handson/qa-bot
       
      -# venv を作成し,依存ライブラリのインストールを行う
      -$ python3 -m venv .env
      -$ source .env/bin/activate
      -$ pip install -r requirements.txt
      +# venv を作成し,依存ライブラリのインストールを行う
      +$ python3 -m venv .env
      +$ source .env/bin/activate
      +$ pip install -r requirements.txt
       
      -# デプロイを実行
      -$ cdk deploy
      +# デプロイを実行 +$ cdk deploy

      デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである.

      CDKデプロイ実行後の出力

      AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと figure_title のような画面が表示されるはずである. EcsClusterQaBot-XXXX という名前ついたクラスターを見つけよう.

      @@ -36192,7 +36192,7 @@ output = json

      それでは,質問をデプロイしたクラウドに提出してみよう.

      ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (run_task.py) を用意した (handson/qa-bot/run_task.py).

      次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.

      -
      sh
      $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
      $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
      +
      sh
      $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"
      $ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?"

      run_task.py を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.

      "ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.

      このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.

      @@ -36207,20 +36207,20 @@ output = json

      タスクの同時実行

      さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. run_task.pyask_many というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は handson/qa-bot/problems.json に定義されている.

      次のようなコマンドを実行しよう.

      -
      sh
      $ python run_task.py ask_many
      $ python run_task.py ask_many
      +
      sh
      $ python run_task.py ask_many
      $ python run_task.py ask_many

      このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (figure_title). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.

      複数の質問タスクを同時に投入する

      すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.

      -
      sh
      $ python run_task.py list_answers
      $ python run_task.py list_answers
      +
      sh
      $ python run_task.py list_answers
      $ python run_task.py list_answers

      結果として, figure_title のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.

       の実行結果

      おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.

      run_task.py で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.

      -
      sh
      $ python run_task.py clear
      $ python run_task.py clear
      +
      sh
      $ python run_task.py clear
      $ python run_task.py clear

      スタックの削除

      これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.

      スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.

      -
      sh
      $ cdk destroy
      $ cdk destroy
      +
      sh
      $ cdk destroy
      $ cdk destroy

      Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する

      ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.

      本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.

      @@ -36249,7 +36249,7 @@ output = json

      準備 でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. アプリケーションの説明 にも関連した情報を記載しているので,併せて参照されたい.

      MNIST 手書き文字認識 (再訪)

      今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, 実践ディープラーニング! MNIST 手書き数字認識タスク で扱った MNIST 手書き文字認識の問題を再度取り上げよう. 実践ディープラーニング! MNIST 手書き数字認識タスク では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.

      -
      python
      optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
      optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
      +
      python
      optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
      optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

      ここで使用された 学習率 (lr=0.01) やモメンタム (momentum=0.5) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,グリッドサーチによるハイパーパラメータサーチを行おう.

      機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.

      グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.

      @@ -36260,18 +36260,18 @@ output = json

      まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.

      Docker イメージのソースコードは handson/aws-batch/docker にある. 基本的に 実践ディープラーニング! MNIST 手書き数字認識タスク のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.

      練習として,この Docker イメージを手元でビルドするところからはじめてみよう. Dockerfile が保存されているディレクトリに移動し, mymnist という名前 (Tag) をつけてビルドを実行する.

      -
      sh
      $ cd handson/aws-batch/docker
      -$ docker build -t mymnist .
      $ cd handson/aws-batch/docker
      -$ docker build -t mymnist .
      +
      sh
      $ cd handson/aws-batch/docker
      +$ docker build -t mymnist .
      $ cd handson/aws-batch/docker
      +$ docker build -t mymnist .

      docker build でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを http://yann.lecun.com/exdb/mnist/ からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.

      手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.

      -
      sh
      $ docker pull tomomano/mymnist:latest
      $ docker pull tomomano/mymnist:latest
      +
      sh
      $ docker pull tomomano/mymnist:latest
      $ docker pull tomomano/mymnist:latest

      イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..

      -
      sh
      $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
      $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
      +
      sh
      $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10
      $ docker run mymnist --lr 0.1 --momentum 0.5 --epochs 10

      このコマンドを実行すると,指定したハイパーパラメータ (--lr で与えられる学習率と --momentum で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は --epochs パラメータで指定する. Hands-on #2: AWS でディープラーニングを実践 のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (figure_title).

      Docker を実行した際の出力

      上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, nvidia-docker の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.

      -
      sh
      $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
      $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
      +
      sh
      $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10
      $ docker run --gpus all mymnist --lr 0.1 --momentum 0.5 --epochs 10

      このコマンドでは,--gpus all というパラメータが加わった.

      CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しないことに気がつくだろう. これを実際にプロットしてみると figure_title のようになるはずである.

      (左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化

      @@ -36305,163 +36305,163 @@ output = json

    それでは,プログラムのソースコードを見てみよう (handson/aws-batch/app.py).

    -
    python
    class SimpleBatch(core.Stack):
    +
    python
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    class SimpleBatch(core.Stack):
    +        #
    +        job_def = batch.JobDefinition(
    +            self, "job-definition",
    +            container=batch.JobDefinitionContainer(
    +                image=ecs.ContainerImage.from_ecr_repository(repo),
    +                command=["python3", "main.py"],
    +                vcpus=4,
    +                gpu_count=1,
    +                memory_limit_mib=12000,
    +                job_role=job_role,
    +                environment={
    +                    "BUCKET_NAME": bucket.bucket_name
    +                }
    +            ),
    +            job_definition_name=self.stack_name + "job-definition",
    +            timeout=core.Duration.hours(2),
    +        )
    class SimpleBatch(core.Stack):
     
    -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    -        super().__init__(scope, name, **kwargs)
    +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
    +        super().__init__(scope, name, **kwargs)
     
    -        #
    -        bucket = s3.Bucket(
    -            self, "bucket",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -            auto_delete_objects=True,
    -        )
    +        #
    +        bucket = s3.Bucket(
    +            self, "bucket",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +            auto_delete_objects=True,
    +        )
     
    -        vpc = ec2.Vpc(
    -            self, "vpc",
    -            # other parameters...
    -        )
    +        vpc = ec2.Vpc(
    +            self, "vpc",
    +            # other parameters...
    +        )
     
    -        #
    -        managed_env = batch.ComputeEnvironment(
    -            self, "managed-env",
    -            compute_resources=batch.ComputeResources(
    -                vpc=vpc,
    -                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    -                desiredv_cpus=0,
    -                maxv_cpus=64,
    -                minv_cpus=0,
    -                instance_types=[
    -                    ec2.InstanceType("g4dn.xlarge")
    -                ],
    -            ),
    -            managed=True,
    -            compute_environment_name=self.stack_name + "compute-env"
    -        )
    +        #
    +        managed_env = batch.ComputeEnvironment(
    +            self, "managed-env",
    +            compute_resources=batch.ComputeResources(
    +                vpc=vpc,
    +                allocation_strategy=batch.AllocationStrategy.BEST_FIT,
    +                desiredv_cpus=0,
    +                maxv_cpus=64,
    +                minv_cpus=0,
    +                instance_types=[
    +                    ec2.InstanceType("g4dn.xlarge")
    +                ],
    +            ),
    +            managed=True,
    +            compute_environment_name=self.stack_name + "compute-env"
    +        )
     
    -        #
    -        job_queue = batch.JobQueue(
    -            self, "job-queue",
    -            compute_environments=[
    -                batch.JobQueueComputeEnvironment(
    -                    compute_environment=managed_env,
    -                    order=100
    -                )
    -            ],
    -            job_queue_name=self.stack_name + "job-queue"
    -        )
    +        #
    +        job_queue = batch.JobQueue(
    +            self, "job-queue",
    +            compute_environments=[
    +                batch.JobQueueComputeEnvironment(
    +                    compute_environment=managed_env,
    +                    order=100
    +                )
    +            ],
    +            job_queue_name=self.stack_name + "job-queue"
    +        )
     
    -        #
    -        job_role = iam.Role(
    -            self, "job-role",
    -            assumed_by=iam.CompositePrincipal(
    -                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    -            )
    -        )
    -        # allow read and write access to S3 bucket
    -        bucket.grant_read_write(job_role)
    +        #
    +        job_role = iam.Role(
    +            self, "job-role",
    +            assumed_by=iam.CompositePrincipal(
    +                iam.ServicePrincipal("ecs-tasks.amazonaws.com")
    +            )
    +        )
    +        # allow read and write access to S3 bucket
    +        bucket.grant_read_write(job_role)
     
    -        #
    -        repo = ecr.Repository(
    -            self, "repository",
    -            removal_policy=core.RemovalPolicy.DESTROY,
    -        )
    +        #
    +        repo = ecr.Repository(
    +            self, "repository",
    +            removal_policy=core.RemovalPolicy.DESTROY,
    +        )
     
    -        #
    -        job_def = batch.JobDefinition(
    -            self, "job-definition",
    -            container=batch.JobDefinitionContainer(
    -                image=ecs.ContainerImage.from_ecr_repository(repo),
    -                command=["python3", "main.py"],
    -                vcpus=4,
    -                gpu_count=1,
    -                memory_limit_mib=12000,
    -                job_role=job_role,
    -                environment={
    -                    "BUCKET_NAME": bucket.bucket_name
    -                }
    -            ),
    -            job_definition_name=self.stack_name + "job-definition",
    -            timeout=core.Duration.hours(2),
    -        )
    + # + job_def = batch.JobDefinition( + self, "job-definition", + container=batch.JobDefinitionContainer( + image=ecs.ContainerImage.from_ecr_repository(repo), + command=["python3", "main.py"], + vcpus=4, + gpu_count=1, + memory_limit_mib=12000, + job_role=job_role, + environment={ + "BUCKET_NAME": bucket.bucket_name + } + ), + job_definition_name=self.stack_name + "job-definition", + timeout=core.Duration.hours(2), + )
    • で,計算結果を保存するための S3 バケットを用意している

      @@ -36488,25 +36488,25 @@ output = json

      スタックのデプロイ

      スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.

      デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

      -
      sh
      # プロジェクトのディレクトリに移動
      -$ cd handson/aws-batch
      +
      sh
      # プロジェクトのディレクトリに移動
      +$ cd handson/aws-batch
       
      -# venv を作成し,依存ライブラリのインストールを行う
      -$ python3 -m venv .env
      -$ source .env/bin/activate
      -$ pip install -r requirements.txt
      +# venv を作成し,依存ライブラリのインストールを行う
      +$ python3 -m venv .env
      +$ source .env/bin/activate
      +$ pip install -r requirements.txt
       
      -# デプロイを実行
      -$ cdk deploy
      # プロジェクトのディレクトリに移動
      -$ cd handson/aws-batch
      +# デプロイを実行
      +$ cdk deploy
      # プロジェクトのディレクトリに移動
      +$ cd handson/aws-batch
       
      -# venv を作成し,依存ライブラリのインストールを行う
      -$ python3 -m venv .env
      -$ source .env/bin/activate
      -$ pip install -r requirements.txt
      +# venv を作成し,依存ライブラリのインストールを行う
      +$ python3 -m venv .env
      +$ source .env/bin/activate
      +$ pip install -r requirements.txt
       
      -# デプロイを実行
      -$ cdk deploy
      +# デプロイを実行 +$ cdk deploy

      デプロイのコマンドが無事に実行されたことが確認できたら,AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールの検索バーで batch と入力し, AWS Batch の管理画面を開く (figure_title).

      AWS Batch のコンソール画面 (ダッシュボード)

      まず目を向けてほしいのが,画面の一番下にある Compute environment overview の中の SimpleBatchcompute-env という名前の項目だ. Compute environment とは,先ほど述べたとおり,計算が実行される環境 (クラスターと読み替えてもよい) である. プログラムで指定したとおり, g4dn.xlarge が実際に使用されるインスタンスタイプとして表示されている. また, Minimum vCPUs が 0,Maximum vCPUs が 64 と設定されていることも見て取れる. 加えて,この時点では一つもジョブが走っていないので, Desired vCPUs は 0 になっている. より詳細な Compute environment の情報を閲覧したい場合は,名前をクリックすることで詳細画面が開く.

      @@ -36516,33 +36516,33 @@ output = json

      Docker image を ECR に配置する

      さて, Batch がジョブを実行するには,どこか指定された場所から Docker イメージをダウンロード (pull) してくる必要がある. 前回のハンズオン (Hands-on #3: AWS で自動質問回答ボットを走らせる) では,公開設定にしてある Docker Hub からイメージを pull してきた. 今回のハンズオンでは, AWS から提供されているレジストリである ECR (Elastic Container Registry) に image を配置するという設計を採用する. ECR を利用する利点は,自分だけがアクセスすることのできるプライベートなイメージの置き場所を用意できる点である. Batch は ECR からイメージを pull してくることで,タスクを実行する (figure_title).

      スタックのソースコードでいうと,次の箇所が ECR を定義している.

      -
      python
      #
      -repo = ecr.Repository(
      -    self, "repository",
      -    removal_policy=core.RemovalPolicy.DESTROY,
      -)
      +
      python
      #
      +repo = ecr.Repository(
      +    self, "repository",
      +    removal_policy=core.RemovalPolicy.DESTROY,
      +)
       
      -job_def = batch.JobDefinition(
      -    self, "job-definition",
      -    container=batch.JobDefinitionContainer(
      -        image=ecs.ContainerImage.from_ecr_repository(repo), #
      -        ...
      -    ),
      -    ...
      -)
      #
      -repo = ecr.Repository(
      -    self, "repository",
      -    removal_policy=core.RemovalPolicy.DESTROY,
      -)
      +job_def = batch.JobDefinition(
      +    self, "job-definition",
      +    container=batch.JobDefinitionContainer(
      +        image=ecs.ContainerImage.from_ecr_repository(repo), #
      +        ...
      +    ),
      +    ...
      +)
      #
      +repo = ecr.Repository(
      +    self, "repository",
      +    removal_policy=core.RemovalPolicy.DESTROY,
      +)
       
      -job_def = batch.JobDefinition(
      -    self, "job-definition",
      -    container=batch.JobDefinitionContainer(
      -        image=ecs.ContainerImage.from_ecr_repository(repo), #
      -        ...
      -    ),
      -    ...
      -)
      +job_def = batch.JobDefinition( + self, "job-definition", + container=batch.JobDefinitionContainer( + image=ecs.ContainerImage.from_ecr_repository(repo), # + ... + ), + ... +)
      • で,新規の ECR を作成している.

        @@ -36564,89 +36564,89 @@ output = json

        さて,ここからは実際に AWS Batch にジョブを投入する方法を見ていこう.

        ハンズオンのディレクトリの notebook/ というディレクトリの中に, run_single.ipynb というファイルが見つかるはずである (.ipynb は Jupyter notebook のファイル形式). これを Jupyter notebook から開こう.

        今回のハンズオンでは, venv による仮想環境の中に Jupyter notebook もインストール済みである. なので,ローカルマシンから以下のコマンドで Jupyter notebook を立ち上げる.

        -
        sh
        # .env の仮想環境にいることを確認
        -(.env) $ cd notebook
        -(.env) $ jupyter notebook
        # .env の仮想環境にいることを確認
        -(.env) $ cd notebook
        -(.env) $ jupyter notebook
        +
        sh
        # .env の仮想環境にいることを確認
        +(.env) $ cd notebook
        +(.env) $ jupyter notebook
        # .env の仮想環境にいることを確認
        +(.env) $ cd notebook
        +(.env) $ jupyter notebook

        Jupyter notebook が起動したら, run_single.ipynb を開く.

        最初の [1], [2], [3] 番のセルは,ジョブをサブミットするための関数 (submit_job()) を定義している.

        -
        python
        # [1]
        -import boto3
        -import argparse
        +
        python
        # [1]
        +import boto3
        +import argparse
         
        -# [2]
        -# AWS 認証ヘルパー ...省略...
        +# [2]
        +# AWS 認証ヘルパー ...省略...
         
        -# [3]
        -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
        -    if profile_name is None:
        -        session = boto3.Session()
        -    else:
        -        session = boto3.Session(profile_name=profile_name)
        -    client = session.client("batch")
        +# [3]
        +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
        +    if profile_name is None:
        +        session = boto3.Session()
        +    else:
        +        session = boto3.Session(profile_name=profile_name)
        +    client = session.client("batch")
         
        -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
        -    resp = client.submit_job(
        -        jobName=title,
        -        jobQueue="SimpleBatchjob-queue",
        -        jobDefinition="SimpleBatchjob-definition",
        -        containerOverrides={
        -            "command": ["--lr", str(lr),
        -                        "--momentum", str(momentum),
        -                        "--epochs", str(epochs),
        -                        "--uploadS3", "true"]
        -        }
        -    )
        -    print("Job submitted!")
        -    print("job name", resp["jobName"], "job ID", resp["jobId"])
        # [1]
        -import boto3
        -import argparse
        +    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
        +    resp = client.submit_job(
        +        jobName=title,
        +        jobQueue="SimpleBatchjob-queue",
        +        jobDefinition="SimpleBatchjob-definition",
        +        containerOverrides={
        +            "command": ["--lr", str(lr),
        +                        "--momentum", str(momentum),
        +                        "--epochs", str(epochs),
        +                        "--uploadS3", "true"]
        +        }
        +    )
        +    print("Job submitted!")
        +    print("job name", resp["jobName"], "job ID", resp["jobId"])
        # [1]
        +import boto3
        +import argparse
         
        -# [2]
        -# AWS 認証ヘルパー ...省略...
        +# [2]
        +# AWS 認証ヘルパー ...省略...
         
        -# [3]
        -def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
        -    if profile_name is None:
        -        session = boto3.Session()
        -    else:
        -        session = boto3.Session(profile_name=profile_name)
        -    client = session.client("batch")
        +# [3]
        +def submit_job(lr:float, momentum:float, epochs:int, profile_name="default"):
        +    if profile_name is None:
        +        session = boto3.Session()
        +    else:
        +        session = boto3.Session(profile_name=profile_name)
        +    client = session.client("batch")
         
        -    title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "")
        -    resp = client.submit_job(
        -        jobName=title,
        -        jobQueue="SimpleBatchjob-queue",
        -        jobDefinition="SimpleBatchjob-definition",
        -        containerOverrides={
        -            "command": ["--lr", str(lr),
        -                        "--momentum", str(momentum),
        -                        "--epochs", str(epochs),
        -                        "--uploadS3", "true"]
        -        }
        -    )
        -    print("Job submitted!")
        -    print("job name", resp["jobName"], "job ID", resp["jobId"])
        + title = "lr" + str(lr).replace(".", "") + "_m" + str(momentum).replace(".", "") + resp = client.submit_job( + jobName=title, + jobQueue="SimpleBatchjob-queue", + jobDefinition="SimpleBatchjob-definition", + containerOverrides={ + "command": ["--lr", str(lr), + "--momentum", str(momentum), + "--epochs", str(epochs), + "--uploadS3", "true"] + } + ) + print("Job submitted!") + print("job name", resp["jobName"], "job ID", resp["jobId"])

        submit_job() 関数について簡単に説明しよう. MNIST 手書き文字認識 (再訪) で, MNIST の Docker をローカルで実行したとき,次のようなコマンドを使用した.

        -
        sh
        $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
        $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
        +
        sh
        $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10
        $ docker run -it mymnist --lr 0.1 --momentum 0.5 --epochs 10

        ここで, --lr 0.1 --momentum 0.5 --epochs 10 の部分が,コンテナに渡されるコマンドである.

        AWS Batch でジョブを実行する際も,ContainerOverridescommand というパラメータを使用することで,コンテナに渡されるコマンドを指定することができる. コードでは以下の部分が該当する.

        -
        python
        containerOverrides={
        -    "command": ["--lr", str(lr),
        -                "--momentum", str(momentum),
        -                "--epochs", str(epochs),
        -                "--uploadS3", "true"]
        -}
        containerOverrides={
        -    "command": ["--lr", str(lr),
        -                "--momentum", str(momentum),
        -                "--epochs", str(epochs),
        -                "--uploadS3", "true"]
        -}
        +
        python
        containerOverrides={
        +    "command": ["--lr", str(lr),
        +                "--momentum", str(momentum),
        +                "--epochs", str(epochs),
        +                "--uploadS3", "true"]
        +}
        containerOverrides={
        +    "command": ["--lr", str(lr),
        +                "--momentum", str(momentum),
        +                "--epochs", str(epochs),
        +                "--uploadS3", "true"]
        +}

        続いて, [4] 番のセルに移ろう. ここでは,上記の submit_job() 関数を用いて, 学習率 = 0.01, モメンタム=0.1, エポック数=100 を指定したジョブを投入する.

        -
        python
        # [4]
        -submit_job(0.01, 0.1, 100)
        # [4]
        -submit_job(0.01, 0.1, 100)
        +
        python
        # [4]
        +submit_job(0.01, 0.1, 100)
        # [4]
        +submit_job(0.01, 0.1, 100)

        AWS の認証情報は, Jupyter Notebook の内部から再度定義する必要がある. これを手助けするため, Notebook の [2] 番のセル (デフォルトではすべてコメントアウトされている) を用意した. これを使うにはコメントアウトを解除すればよい. このセルを実行すると, AWS の認証情報を入力する対話的なプロンプトが表示される. プロンプトに従って aws secret key などを入力することで, (Jupyter のセッションに固有な) 環境変数に AWS の認証情報が記録される.

        もう一つの認証方法として, submit_job() 関数に profile_name というパラメータを用意した. もし ~/.aws/credentials に認証情報が書き込まれているのならば (詳しくは AWS CLI のインストール), profile_name に使用したいプロファイルの名前を渡すだけで, 認証を行うことができる. 慣れている読者は後者のほうが便利であると感じるだろう.

        [4] 番のセルを実行したら,ジョブが実際に投入されたかどうかを AWS コンソールから確認してみよう. AWS Batch の管理コンソールを開くと, figure_title のような画面が表示されるだろう.

        @@ -36658,124 +36658,124 @@ output = json

        S3 のコンソールに行くと simplebatch-bucketXXXX (XXXX の部分はユーザーによって異なる) という名前のバケットが見つかるはずである. これをクリックして中身を見てみると, metrics_lr0.0100_m0.1000.csv という名前の CSV があることが確認できるだろう (figure_title). これが, 学習率 = 0.01, モメンタム = 0.1 として学習を行ったときの結果である.

        ジョブの実行結果は S3 に保存される

        さて,ここで run_single.ipynb に戻ってこよう. [5] から [7] 番のセルでは,学習結果の CSV ファイルのダウンロードを行っている.

        -
        python
        # [5]
        -import pandas as pd
        -import io
        -from matplotlib import pyplot as plt
        +
        python
        # [5]
        +import pandas as pd
        +import io
        +from matplotlib import pyplot as plt
         
        -# [6]
        -def read_table_from_s3(bucket_name, key, profile_name=None):
        -    if profile_name is None:
        -        session = boto3.Session()
        -    else:
        -        session = boto3.Session(profile_name=profile_name)
        -    s3 = session.resource("s3")
        -    bucket = s3.Bucket(bucket_name)
        +# [6]
        +def read_table_from_s3(bucket_name, key, profile_name=None):
        +    if profile_name is None:
        +        session = boto3.Session()
        +    else:
        +        session = boto3.Session(profile_name=profile_name)
        +    s3 = session.resource("s3")
        +    bucket = s3.Bucket(bucket_name)
         
        -    obj = bucket.Object(key).get().get("Body")
        -    df = pd.read_csv(obj)
        +    obj = bucket.Object(key).get().get("Body")
        +    df = pd.read_csv(obj)
         
        -    return df
        +    return df
         
        -# [7]
        -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
        -df = read_table_from_s3(
        -    bucket_name,
        -    "metrics_lr0.0100_m0.1000.csv"
        -)
        # [5]
        -import pandas as pd
        -import io
        -from matplotlib import pyplot as plt
        +# [7]
        +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
        +df = read_table_from_s3(
        +    bucket_name,
        +    "metrics_lr0.0100_m0.1000.csv"
        +)
        # [5]
        +import pandas as pd
        +import io
        +from matplotlib import pyplot as plt
         
        -# [6]
        -def read_table_from_s3(bucket_name, key, profile_name=None):
        -    if profile_name is None:
        -        session = boto3.Session()
        -    else:
        -        session = boto3.Session(profile_name=profile_name)
        -    s3 = session.resource("s3")
        -    bucket = s3.Bucket(bucket_name)
        +# [6]
        +def read_table_from_s3(bucket_name, key, profile_name=None):
        +    if profile_name is None:
        +        session = boto3.Session()
        +    else:
        +        session = boto3.Session(profile_name=profile_name)
        +    s3 = session.resource("s3")
        +    bucket = s3.Bucket(bucket_name)
         
        -    obj = bucket.Object(key).get().get("Body")
        -    df = pd.read_csv(obj)
        +    obj = bucket.Object(key).get().get("Body")
        +    df = pd.read_csv(obj)
         
        -    return df
        +    return df
         
        -# [7]
        -bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu"
        -df = read_table_from_s3(
        -    bucket_name,
        -    "metrics_lr0.0100_m0.1000.csv"
        -)
        +# [7] +bucket_name = "simplebatch-bucket43879c71-mbqaltx441fu" +df = read_table_from_s3( + bucket_name, + "metrics_lr0.0100_m0.1000.csv" +)

        [6] で S3 から CSV データをダウンロードし, pandas の DataFrame オブジェクトとしてロードする関数を定義している. [7] を実行する際, bucket_name という変数の値を,自分自身のバケットの名前に置き換えることに注意しよう (先ほど S3 コンソールから確認した simplebatch-bucketXXXX のことである).

        続いて, [9] 番のセルで, CSV のデータをプロットしている (figure_title). ローカルで実行したときと同じように, AWS Batch を用いて MNIST モデルを訓練することに成功した!

        -
        python
        # [9]
        -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
        -x = [i for i in range(df.shape[0])]
        -ax1.plot(x, df["train_loss"], label="Train")
        -ax1.plot(x, df["val_loss"], label="Val")
        -ax2.plot(x, df["val_accuracy"])
        +
        python
        # [9]
        +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
        +x = [i for i in range(df.shape[0])]
        +ax1.plot(x, df["train_loss"], label="Train")
        +ax1.plot(x, df["val_loss"], label="Val")
        +ax2.plot(x, df["val_accuracy"])
         
        -ax1.set_xlabel("Epochs")
        -ax1.set_ylabel("Loss")
        -ax1.legend()
        +ax1.set_xlabel("Epochs")
        +ax1.set_ylabel("Loss")
        +ax1.legend()
         
        -ax2.set_xlabel("Epochs")
        -ax2.set_ylabel("Accuracy")
        +ax2.set_xlabel("Epochs")
        +ax2.set_ylabel("Accuracy")
         
        -print("Best loss:", df["val_loss"].min())
        -print("Best loss epoch:", df["val_loss"].argmin())
        -print("Best accuracy:", df["val_accuracy"].max())
        -print("Best accuracy epoch:", df["val_accuracy"].argmax())
        # [9]
        -fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
        -x = [i for i in range(df.shape[0])]
        -ax1.plot(x, df["train_loss"], label="Train")
        -ax1.plot(x, df["val_loss"], label="Val")
        -ax2.plot(x, df["val_accuracy"])
        +print("Best loss:", df["val_loss"].min())
        +print("Best loss epoch:", df["val_loss"].argmin())
        +print("Best accuracy:", df["val_accuracy"].max())
        +print("Best accuracy epoch:", df["val_accuracy"].argmax())
        # [9]
        +fig, (ax1, ax2) = plt.subplots(1,2, figsize=(9,4))
        +x = [i for i in range(df.shape[0])]
        +ax1.plot(x, df["train_loss"], label="Train")
        +ax1.plot(x, df["val_loss"], label="Val")
        +ax2.plot(x, df["val_accuracy"])
         
        -ax1.set_xlabel("Epochs")
        -ax1.set_ylabel("Loss")
        -ax1.legend()
        +ax1.set_xlabel("Epochs")
        +ax1.set_ylabel("Loss")
        +ax1.legend()
         
        -ax2.set_xlabel("Epochs")
        -ax2.set_ylabel("Accuracy")
        +ax2.set_xlabel("Epochs")
        +ax2.set_ylabel("Accuracy")
         
        -print("Best loss:", df["val_loss"].min())
        -print("Best loss epoch:", df["val_loss"].argmin())
        -print("Best accuracy:", df["val_accuracy"].max())
        -print("Best accuracy epoch:", df["val_accuracy"].argmax())
        +print("Best loss:", df["val_loss"].min()) +print("Best loss epoch:", df["val_loss"].argmin()) +print("Best accuracy:", df["val_accuracy"].max()) +print("Best accuracy epoch:", df["val_accuracy"].argmax())

        AWS Batch で行った MNIST モデルの学習の結果

        並列に複数の Job を実行する

        さて,ここからが最後の仕上げである. ここまでのハンズオンで構築した AWS Batch のシステムを使って,ハイパーパラメータサーチを実際に行おう.

        先ほど実行した run_single.ipynb と同じディレクトリにある run_sweep.ipynb を開く.

        セル [1], [2], [3] は run_single.ipynb と同一である.

        -
        python
        # [1]
        -import boto3
        -import argparse
        +
        python
        # [1]
        +import boto3
        +import argparse
         
        -# [2]
        -# AWS 認証ヘルパー ...省略...
        +# [2]
        +# AWS 認証ヘルパー ...省略...
         
        -# [3]
        -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
        -    # ...省略...
        # [1]
        -import boto3
        -import argparse
        +# [3]
        +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
        +    # ...省略...
        # [1]
        +import boto3
        +import argparse
         
        -# [2]
        -# AWS 認証ヘルパー ...省略...
        +# [2]
        +# AWS 認証ヘルパー ...省略...
         
        -# [3]
        -def submit_job(lr:float, momentum:float, epochs:int, profile_name=None):
        -    # ...省略...
        +# [3] +def submit_job(lr:float, momentum:float, epochs:int, profile_name=None): + # ...省略...

        セル [4] の for ループを使って,グリッド状にハイパーパラメータの組み合わせを用意し, batch にジョブを投入している. ここでは 3x3=9 個のジョブを作成した.

        -
        python
        # [4]
        -for lr in [0.1, 0.01, 0.001]:
        -    for m in [0.5, 0.1, 0.05]:
        -        submit_job(lr, m, 100)
        # [4]
        -for lr in [0.1, 0.01, 0.001]:
        -    for m in [0.5, 0.1, 0.05]:
        -        submit_job(lr, m, 100)
        +
        python
        # [4]
        +for lr in [0.1, 0.01, 0.001]:
        +    for m in [0.5, 0.1, 0.05]:
        +        submit_job(lr, m, 100)
        # [4]
        +for lr in [0.1, 0.01, 0.001]:
        +    for m in [0.5, 0.1, 0.05]:
        +        submit_job(lr, m, 100)

        セル [4] を実行したら, Batch のコンソールを開こう. 先ほどと同様に,ジョブのステータスは SUBMITTED > RUNNABLE > STARTING > RUNNING と移り変わっていくことがわかるだろう. 最終的に 9 個のジョブがすべて RUNNING の状態になることを確認しよう (figure_title). また,このとき Compute environment の Desired vCPUs は 4x9=36 となっていることを確認しよう (figure_title).

        複数のジョブを同時投入したときの Batch コンソール

        次に,Batch のコンソールの左側のメニューから Jobs をクリックしてみよう. ここでは,実行中のジョブの一覧が確認することができる (figure_title). ジョブのステータスでフィルタリングをすることも可能である. 9 個のジョブがどれも RUNNING 状態にあることが確認できるだろう.

        @@ -36785,81 +36785,81 @@ output = json

        ここまで確認できたら,それぞれの Job が終了するまでしばらく待とう (だいたい 10-15 分くらいで終わる). すべてのジョブが終了すると,ダッシュボードの SUCCEEDED が 9 となっているはずだ. また, Compute environment の Desired vCPUs も 0 に落ちていることを確認しよう. 最後に EC2 コンソールに行って,すべての g4dn インスタンスが停止していることを確認しよう.

        以上から, AWS Batch を使うことで,ジョブの投入に応じて自動的に EC2 インスタンスが起動され,ジョブの完了とともに,ただちにインスタンスの停止が行われる一連の挙動を観察することができた. 一つのジョブの完了におよそ 10 分の時間がかかるので,9 個のハイパーパラメータの組を逐次的に計算していた場合は 90 分の時間を要することになる. AWS Batch を使ってこれらの計算を並列に実行することで,ジョブ一個分の計算時間 (=10 分) ですべての計算を終えることができた!

        さて,再び run_sweep.ipynb に戻ってこよう. [5] 以降のセルでは,グリッドサーチの結果を可視化している.

        -
        python
        # [5]
        -import pandas as pd
        -import numpy as np
        -import io
        -from matplotlib import pyplot as plt
        +
        python
        # [5]
        +import pandas as pd
        +import numpy as np
        +import io
        +from matplotlib import pyplot as plt
         
        -# [6]
        -def read_table_from_s3(bucket_name, key, profile_name=None):
        -    if profile_name is None:
        -        session = boto3.Session()
        -    else:
        -        session = boto3.Session(profile_name=profile_name)
        -    s3 = session.resource("s3")
        -    bucket = s3.Bucket(bucket_name)
        +# [6]
        +def read_table_from_s3(bucket_name, key, profile_name=None):
        +    if profile_name is None:
        +        session = boto3.Session()
        +    else:
        +        session = boto3.Session(profile_name=profile_name)
        +    s3 = session.resource("s3")
        +    bucket = s3.Bucket(bucket_name)
         
        -    obj = bucket.Object(key).get().get("Body")
        -    df = pd.read_csv(obj)
        +    obj = bucket.Object(key).get().get("Body")
        +    df = pd.read_csv(obj)
         
        -    return df
        +    return df
         
        -# [7]
        -grid = np.zeros((3,3))
        -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
        -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
        -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
        -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
        -        grid[i,j] = df["val_accuracy"].max()
        +# [7]
        +grid = np.zeros((3,3))
        +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
        +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
        +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
        +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
        +        grid[i,j] = df["val_accuracy"].max()
         
        -# [8]
        -fig, ax = plt.subplots(figsize=(6,6))
        -ax.set_aspect('equal')
        +# [8]
        +fig, ax = plt.subplots(figsize=(6,6))
        +ax.set_aspect('equal')
         
        -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
        +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
         
        -for i in range(3):
        -    for j in range(3):
        -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
        -                       ha="center", va="center", color="w")
        # [5]
        -import pandas as pd
        -import numpy as np
        -import io
        -from matplotlib import pyplot as plt
        +for i in range(3):
        +    for j in range(3):
        +        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
        +                       ha="center", va="center", color="w")
        # [5]
        +import pandas as pd
        +import numpy as np
        +import io
        +from matplotlib import pyplot as plt
         
        -# [6]
        -def read_table_from_s3(bucket_name, key, profile_name=None):
        -    if profile_name is None:
        -        session = boto3.Session()
        -    else:
        -        session = boto3.Session(profile_name=profile_name)
        -    s3 = session.resource("s3")
        -    bucket = s3.Bucket(bucket_name)
        +# [6]
        +def read_table_from_s3(bucket_name, key, profile_name=None):
        +    if profile_name is None:
        +        session = boto3.Session()
        +    else:
        +        session = boto3.Session(profile_name=profile_name)
        +    s3 = session.resource("s3")
        +    bucket = s3.Bucket(bucket_name)
         
        -    obj = bucket.Object(key).get().get("Body")
        -    df = pd.read_csv(obj)
        +    obj = bucket.Object(key).get().get("Body")
        +    df = pd.read_csv(obj)
         
        -    return df
        +    return df
         
        -# [7]
        -grid = np.zeros((3,3))
        -for (i, lr) in enumerate([0.1, 0.01, 0.001]):
        -    for (j, m) in enumerate([0.5, 0.1, 0.05]):
        -        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
        -        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
        -        grid[i,j] = df["val_accuracy"].max()
        +# [7]
        +grid = np.zeros((3,3))
        +for (i, lr) in enumerate([0.1, 0.01, 0.001]):
        +    for (j, m) in enumerate([0.5, 0.1, 0.05]):
        +        key = f"metrics_lr{lr:0.4f}_m{m:0.4f}.csv"
        +        df = read_table_from_s3("simplebatch-bucket43879c71-mbqaltx441fu", key)
        +        grid[i,j] = df["val_accuracy"].max()
         
        -# [8]
        -fig, ax = plt.subplots(figsize=(6,6))
        -ax.set_aspect('equal')
        +# [8]
        +fig, ax = plt.subplots(figsize=(6,6))
        +ax.set_aspect('equal')
         
        -c = ax.pcolor(grid, edgecolors='w', linewidths=2)
        +c = ax.pcolor(grid, edgecolors='w', linewidths=2)
         
        -for i in range(3):
        -    for j in range(3):
        -        text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}",
        -                       ha="center", va="center", color="w")
        +for i in range(3): + for j in range(3): + text = ax.text(j+0.5, i+0.5, f"{grid[i, j]:0.1f}", + ha="center", va="center", color="w")

        最終的に出力されるプロットが figure_title である.

        ハイパーパラメータのグリッドサーチの結果

        このプロットから,差は僅かであるが,学習率が 0.1 のときに精度は最大となることがわかる. また,学習率 0.1 のときはモメンタムを変えても大きな差は生じないことが見て取れる.

        @@ -36872,9 +36872,9 @@ output = json

        ECR の Docker image を削除するには, ECR のコンソールに行き,イメージが配置されたレポジトリを開く. そして,画面右上の DELETE ボタンを押して削除する (figure_title).

        ECR から Docker image を削除する

        あるいは, AWS CLI から同様の操作を行うには,以下のコマンドを用いる (XXXX は自分の ECR レポジトリ名に置き換える).

        -
        sh
        $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
        $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
        +
        sh
        $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest
        $ aws ecr batch-delete-image --repository-name XXXX --image-ids imageTag=latest

        image の削除が完了したうえで,次のコマンドでスタックを削除する.

        -
        sh
        $ cdk destroy
        $ cdk destroy
        +
        sh
        $ cdk destroy
        $ cdk destroy

        (#sec:batch_development_and_debug) === クラウドを用いた機械学習アプリケーションの開発とデバッグ

        本章で紹介したハンズオンでは, AWS Batch を使用することでニューラルネットの学習を複数並列に実行し,高速化を実現した. 本章の最後の話題として,クラウドを用いた機械学習アプリケーションの開発とデバッグの方法について述べよう.

        ローカルに GPU を搭載した強力なマシンがなく,クラウドを利用する予算が確保されているのであれば, figure_title のような開発のスキームが理想的であると考える. 最初の段階では, Hands-on #2: AWS でディープラーニングを実践 で見たような方法で, GPU 搭載型の EC2 インスタンスを作成し, Jupyter Notebook などのインタラクティブな環境で様々なモデルを試し実験を行う. Jupyter である程度アプリケーションが完成してきたタイミングで,作成したアプリケーションを Docker イメージにパッケージングする. そして, EC2 上で docker run を行い,作成したイメージがバグなく動作するか確認を行う. その次に,ハイパーパラメータの最適化などのチューニングを, Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する のハンズオンで学んだ AWS Batch などの計算システムを利用して行う. よい深層学習モデルが完成したら,仕上げに大規模データへの推論処理を行うシステムを Hands-on #3: AWS で自動質問回答ボットを走らせる を参考に構築する.

        @@ -36995,59 +36995,59 @@ output = json

        Lambda チュートリアルの概要

        このハンズオンは,基本的に AWS Lambda の無料枠 の範囲内で実行することができる.

        app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

        -
        py
        #
        -FUNC = """
        -import time
        -from random import choice, randint
        -def handler(event, context):
        -    time.sleep(randint(2,5))
        -    sushi = ["salmon", "tuna", "squid"]
        -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
        -    print(message)
        -    return message
        -"""
        +
        py
        #
        +FUNC = """
        +import time
        +from random import choice, randint
        +def handler(event, context):
        +    time.sleep(randint(2,5))
        +    sushi = ["salmon", "tuna", "squid"]
        +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
        +    print(message)
        +    return message
        +"""
         
        -class SimpleLambda(core.Stack):
        +class SimpleLambda(core.Stack):
         
        -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
        -        super().__init__(scope, name, **kwargs)
        +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
        +        super().__init__(scope, name, **kwargs)
         
        -        #
        -        handler = _lambda.Function(
        -            self, 'LambdaHandler',
        -            runtime=_lambda.Runtime.PYTHON_3_7,
        -            code=_lambda.Code.from_inline(FUNC),
        -            handler="index.handler",
        -            memory_size=128,
        -            timeout=core.Duration.seconds(10),
        -            dead_letter_queue_enabled=True,
        -        )
        #
        -FUNC = """
        -import time
        -from random import choice, randint
        -def handler(event, context):
        -    time.sleep(randint(2,5))
        -    sushi = ["salmon", "tuna", "squid"]
        -    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
        -    print(message)
        -    return message
        -"""
        +        #
        +        handler = _lambda.Function(
        +            self, 'LambdaHandler',
        +            runtime=_lambda.Runtime.PYTHON_3_7,
        +            code=_lambda.Code.from_inline(FUNC),
        +            handler="index.handler",
        +            memory_size=128,
        +            timeout=core.Duration.seconds(10),
        +            dead_letter_queue_enabled=True,
        +        )
        #
        +FUNC = """
        +import time
        +from random import choice, randint
        +def handler(event, context):
        +    time.sleep(randint(2,5))
        +    sushi = ["salmon", "tuna", "squid"]
        +    message = "Welcome to Cloud Sushi. Your order is " + choice(sushi)
        +    print(message)
        +    return message
        +"""
         
        -class SimpleLambda(core.Stack):
        +class SimpleLambda(core.Stack):
         
        -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
        -        super().__init__(scope, name, **kwargs)
        +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
        +        super().__init__(scope, name, **kwargs)
         
        -        #
        -        handler = _lambda.Function(
        -            self, 'LambdaHandler',
        -            runtime=_lambda.Runtime.PYTHON_3_7,
        -            code=_lambda.Code.from_inline(FUNC),
        -            handler="index.handler",
        -            memory_size=128,
        -            timeout=core.Duration.seconds(10),
        -            dead_letter_queue_enabled=True,
        -        )
        + # + handler = _lambda.Function( + self, 'LambdaHandler', + runtime=_lambda.Runtime.PYTHON_3_7, + code=_lambda.Code.from_inline(FUNC), + handler="index.handler", + memory_size=128, + timeout=core.Duration.seconds(10), + dead_letter_queue_enabled=True, + )
        • ここで, Lambda で実行されるべき関数を定義している. これは非常に単純な関数で,2-5 秒のランダムな時間スリープした後,["salmon", "tuna", "squid"] のいずれかの文字列をランダムに選択し, "Welcome to Cloud Sushi. Your order is XXXX" (XXXX は選ばれた寿司のネタ) というメッセージをリターンする.

          @@ -37079,25 +37079,25 @@ output = json

          上記のプログラムを実行することで, Lambda 関数がクラウド上に作成される. 早速デプロイしてみよう.

          デプロイ

          デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (AWS CLI のインストール).

          -
          sh
          # プロジェクトのディレクトリに移動
          -$ cd handson/serverless/lambda
          +
          sh
          # プロジェクトのディレクトリに移動
          +$ cd handson/serverless/lambda
           
          -# venv を作成し,依存ライブラリのインストールを行う
          -$ python3 -m venv .env
          -$ source .env/bin/activate
          -$ pip install -r requirements.txt
          +# venv を作成し,依存ライブラリのインストールを行う
          +$ python3 -m venv .env
          +$ source .env/bin/activate
          +$ pip install -r requirements.txt
           
          -# デプロイを実行
          -$ cdk deploy
          # プロジェクトのディレクトリに移動
          -$ cd handson/serverless/lambda
          +# デプロイを実行
          +$ cdk deploy
          # プロジェクトのディレクトリに移動
          +$ cd handson/serverless/lambda
           
          -# venv を作成し,依存ライブラリのインストールを行う
          -$ python3 -m venv .env
          -$ source .env/bin/activate
          -$ pip install -r requirements.txt
          +# venv を作成し,依存ライブラリのインストールを行う
          +$ python3 -m venv .env
          +$ source .env/bin/activate
          +$ pip install -r requirements.txt
           
          -# デプロイを実行
          -$ cdk deploy
          +# デプロイを実行 +$ cdk deploy

          デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleLambda.FunctionName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

          CDKデプロイ実行後の出力

          AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから,Lambda のページに行くと figure_title のような画面から Lambda の関数の一覧が確認できる.

          @@ -37108,15 +37108,15 @@ output = json

          Lambda 関数の実行

          それでは,作成した Lambda 関数を実行 (invoke) してみよう. AWS の API を使うことで,関数の実行をスタートすることができる. 今回は, handson/serverless/lambda/invoke_one.py に関数を実行するための簡単なプログラムを提供している. 興味のある読者はコードを読んでもらいたい.

          以下のコマンドで,Lambda の関数を実行する. コマンドの XXXX の部分は,先ほどデプロイしたときに SimpleLambda.FunctionName = XXXX で得られた XXXX の文字列で置換する.

          -
          sh
          $ python invoke_one.py XXXX
          $ python invoke_one.py XXXX
          +
          sh
          $ python invoke_one.py XXXX
          $ python invoke_one.py XXXX

          すると, "Welcome to Cloud Sushi. Your order is salmon" という出力が得られるはずだ. とてもシンプルではあるが,クラウド上で先ほどの関数が走り,乱数が生成されたうえで,ランダムな寿司ネタが選択されて出力が返されている. このコマンドを何度か打ってみて,実行ごとに異なる寿司ネタが返されることを確認しよう.

          さて,このコマンドは,一度につき一回の関数を実行したわけであるが, Lambda の本領は一度に大量のタスクを同時に実行できる点である. そこで,今度は一度に 100 個のタスクを同時に送信してみよう. handson/serverless/lambda/invoke_many.py のスクリプトを使用する.

          次のコマンドを実行しよう. XXXX の部分は前述と同様に置き換える. 第二引数の 100 は 100 個のタスクを投入せよ,という意味である.

          -
          sh
          $ python invoke_many.py XXXX 100
          $ python invoke_many.py XXXX 100
          +
          sh
          $ python invoke_many.py XXXX 100
          $ python invoke_many.py XXXX 100

          すると次のような出力が得られるはずだ.

          -
          sh
          ....................................................................................................
          -Submitted 100 tasks to Lambda!
          ....................................................................................................
          -Submitted 100 tasks to Lambda!
          +
          sh
          ....................................................................................................
          +Submitted 100 tasks to Lambda!
          ....................................................................................................
          +Submitted 100 tasks to Lambda!

          実際に,100 個のタスクが同時に実行されていることを確認しよう. figure_title の画面に戻り, "Monitoring" というタブがあるので,それをクリックする. すると, figure_title のようなグラフが表示されるだろう.

          Lambda コンソール - 関数の実行のモニタリング

          figure_title のグラフの更新には数分かかることがあるので,なにも表示されない場合は少し待つ.

          @@ -37126,44 +37126,44 @@ output = json

          興味がある人は,一気に 1000 個などのジョブを投入してみるとよい. Lambda はそのような大量のリクエストにも対応できることが確認できるだろう. が,あまりやりすぎると Lambda の無料利用枠を超えて料金が発生してしまうので注意.

          スタックの削除

          最後にスタックを削除しよう. スタックを削除するには,次のコマンドを実行すればよい.

          -
          sh
          $ cdk destroy
          $ cdk destroy
          +
          sh
          $ cdk destroy
          $ cdk destroy

          DynamoDB ハンズオン

          続いて, DynamoDB の簡単なチュートリアルをやってみよう. ハンズオンのソースコードは GitHub の /handson/serverless/dynamodb に置いてある.

          このハンズオンで使用するアプリケーションのスケッチを figure_title に示す. STEP 1 では,AWS CDK を使用して DynamoDB のテーブルを初期化し,デプロイする. 続いて STEP 2 では, API を使用してデータベースのデータの書き込み・読み出し・削除などの操作を練習する.

          DynamoDB チュートリアルの概要

          このハンズオンは,基本的に AWS DynamoDB の無料枠 の範囲内で実行できる.

          handson/serverless/dynamodb/app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

          -
          python
          class SimpleDynamoDb(core.Stack):
          -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
          -        super().__init__(scope, name, **kwargs)
          +
          python
          class SimpleDynamoDb(core.Stack):
          +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
          +        super().__init__(scope, name, **kwargs)
           
          -        table = ddb.Table(
          -            self, "SimpleTable",
          -            #
          -            partition_key=ddb.Attribute(
          -                name="item_id",
          -                type=ddb.AttributeType.STRING
          -            ),
          -            #
          -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
          -            #
          -            removal_policy=core.RemovalPolicy.DESTROY
          -        )
          class SimpleDynamoDb(core.Stack):
          -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
          -        super().__init__(scope, name, **kwargs)
          +        table = ddb.Table(
          +            self, "SimpleTable",
          +            #
          +            partition_key=ddb.Attribute(
          +                name="item_id",
          +                type=ddb.AttributeType.STRING
          +            ),
          +            #
          +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
          +            #
          +            removal_policy=core.RemovalPolicy.DESTROY
          +        )
          class SimpleDynamoDb(core.Stack):
          +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
          +        super().__init__(scope, name, **kwargs)
           
          -        table = ddb.Table(
          -            self, "SimpleTable",
          -            #
          -            partition_key=ddb.Attribute(
          -                name="item_id",
          -                type=ddb.AttributeType.STRING
          -            ),
          -            #
          -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
          -            #
          -            removal_policy=core.RemovalPolicy.DESTROY
          -        )
          + table = ddb.Table( + self, "SimpleTable", + # + partition_key=ddb.Attribute( + name="item_id", + type=ddb.AttributeType.STRING + ), + # + billing_mode=ddb.BillingMode.PAY_PER_REQUEST, + # + removal_policy=core.RemovalPolicy.DESTROY + )

          このコードで,最低限の設定がなされた空の DynamoDB テーブルが作成される. それぞれのパラメータの意味を簡単に解説しよう.

          • @@ -37178,25 +37178,25 @@ output = json

          デプロイ

          デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

          -
          sh
          # プロジェクトのディレクトリに移動
          -$ cd handson/serverless/dynamodb
          +
          sh
          # プロジェクトのディレクトリに移動
          +$ cd handson/serverless/dynamodb
           
          -# venv を作成し,依存ライブラリのインストールを行う
          -$ python3 -m venv .env
          -$ source .env/bin/activate
          -$ pip install -r requirements.txt
          +# venv を作成し,依存ライブラリのインストールを行う
          +$ python3 -m venv .env
          +$ source .env/bin/activate
          +$ pip install -r requirements.txt
           
          -# デプロイを実行
          -$ cdk deploy
          # プロジェクトのディレクトリに移動
          -$ cd handson/serverless/dynamodb
          +# デプロイを実行
          +$ cdk deploy
          # プロジェクトのディレクトリに移動
          +$ cd handson/serverless/dynamodb
           
          -# venv を作成し,依存ライブラリのインストールを行う
          -$ python3 -m venv .env
          -$ source .env/bin/activate
          -$ pip install -r requirements.txt
          +# venv を作成し,依存ライブラリのインストールを行う
          +$ python3 -m venv .env
          +$ source .env/bin/activate
          +$ pip install -r requirements.txt
           
          -# デプロイを実行
          -$ cdk deploy
          +# デプロイを実行 +$ cdk deploy

          デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている SimpleDynamoDb.TableName = XXXX の XXXX の文字列は後で使うのでメモしておこう.

          CDKデプロイ実行後の出力

          AWS コンソールにログインして,デプロイされたスタックを確認してみよう. コンソールから, DynamoDB のページに行き,左のメニューバーから "Tables" を選択する. すると, figure_title のような画面からテーブルの一覧が確認できる.

          @@ -37206,167 +37206,167 @@ output = json

          データの読み書き

          それでは, デプロイ で作ったテーブルを使ってデータの読み書きを実践してみよう. ここでは Python と boto3 ライブラリを用いた方法を紹介する.

          まずは,テーブルに新しい要素を追加してみよう. ハンズオンのディレクトリにある simple_write.py を開いてみよう. 中には次のような関数が書かれている.

          -
          python
          import boto3
          -from uuid import uuid4
          -ddb = boto3.resource('dynamodb')
          +
          python
          import boto3
          +from uuid import uuid4
          +ddb = boto3.resource('dynamodb')
           
          -def write_item(table_name):
          -    table = ddb.Table(table_name)
          -    table.put_item(
          -    Item={
          -        'item_id': str(uuid4()),
          -        'first_name': 'John',
          -        'last_name': 'Doe',
          -        'age': 25,
          -        }
          -    )
          import boto3
          -from uuid import uuid4
          -ddb = boto3.resource('dynamodb')
          +def write_item(table_name):
          +    table = ddb.Table(table_name)
          +    table.put_item(
          +    Item={
          +        'item_id': str(uuid4()),
          +        'first_name': 'John',
          +        'last_name': 'Doe',
          +        'age': 25,
          +        }
          +    )
          import boto3
          +from uuid import uuid4
          +ddb = boto3.resource('dynamodb')
           
          -def write_item(table_name):
          -    table = ddb.Table(table_name)
          -    table.put_item(
          -    Item={
          -        'item_id': str(uuid4()),
          -        'first_name': 'John',
          -        'last_name': 'Doe',
          -        'age': 25,
          -        }
          -    )
          +def write_item(table_name): + table = ddb.Table(table_name) + table.put_item( + Item={ + 'item_id': str(uuid4()), + 'first_name': 'John', + 'last_name': 'Doe', + 'age': 25, + } + )

          コードを上から読んでいくと,まず最初に boto3 ライブラリをインポートし, dynamodb のリソースを呼び出している. write_item() 関数は, DynamoDB のテーブルの名前 (上で見た SimpleDynamoDb-XXXX) を引数として受け取る. そして, put_item() メソッドを呼ぶことで,新しいアイテムを DB に書き込んでいる. アイテムには item_id, first_name, last_name, age の 4 つの属性が定義されている. ここで, item_id は先ほど説明した Partition key に相当しており, UUID4 を用いたランダムな文字列を割り当てている.

          では, simple_write.py を実行してみよう. "XXXX" の部分を自分がデプロイしたテーブルの名前 (SimpleDynamoDb で始まる文字列) に置き換えたうえで,次のコマンドを実行する.

          -
          sh
          $ python simple_write.py XXXX
          $ python simple_write.py XXXX
          +
          sh
          $ python simple_write.py XXXX
          $ python simple_write.py XXXX

          新しい要素が正しく書き込めたか, AWS コンソールから確認してみよう. figure_title と同じ手順で,テーブルの中身の要素の一覧を表示する. すると figure_title のように,期待通り新しい要素が見つかるだろう.

          DynamoDB に新しい要素が追加されたことを確認

          boto3 を使ってテーブルから要素を読みだすことも可能である. ハンズオンのディレクトリにある simple_read.py を見てみよう.

          -
          python
          import boto3
          -ddb = boto3.resource('dynamodb')
          +
          python
          import boto3
          +ddb = boto3.resource('dynamodb')
           
          -def scan_table(table_name):
          -    table = ddb.Table(table_name)
          -    items = table.scan().get("Items")
          -    print(items)
          import boto3
          -ddb = boto3.resource('dynamodb')
          +def scan_table(table_name):
          +    table = ddb.Table(table_name)
          +    items = table.scan().get("Items")
          +    print(items)
          import boto3
          +ddb = boto3.resource('dynamodb')
           
          -def scan_table(table_name):
          -    table = ddb.Table(table_name)
          -    items = table.scan().get("Items")
          -    print(items)
          +def scan_table(table_name): + table = ddb.Table(table_name) + items = table.scan().get("Items") + print(items)

          table.scan().get("Items") によって,テーブルの中にあるすべての要素を読みだしている.

          次のコマンドで,このスクリプトを実行してみよう ("XXXX" の部分を正しく置き換えることを忘れずに).

          -
          sh
          $ python simple_read.py XXXX
          $ python simple_read.py XXXX
          +
          sh
          $ python simple_read.py XXXX
          $ python simple_read.py XXXX

          先ほど書き込んだ要素が出力されることを確認しよう.

          大量のデータの読み書き

          DynamoDB の利点は,最初に述べたとおり,負荷に応じて自在にその処理能力を拡大できる点である.

          そこで,ここでは一度に大量のデータを書き込む場合をシミュレートしてみよう. batch_rw.py に,一度に大量の書き込みを実行するためのプログラムが書いてある.

          次のコマンドを実行してみよう (XXXX は自分のテーブルの名前に置き換える).

          -
          sh
          $ python batch_rw.py XXXX write 1000
          $ python batch_rw.py XXXX write 1000
          +
          sh
          $ python batch_rw.py XXXX write 1000
          $ python batch_rw.py XXXX write 1000

          このコマンドを実行することで,ランダムなデータが 1000 個データベースに書き込まれる.

          さらに,データベースの検索をかけてみよう. 今回書き込んだデータには age という属性に 1 から 50 のランダムな整数が割り当てられている. age が 2 以下であるような要素だけを検索し拾ってくるには,次のコマンドを実行すればよい.

          -
          sh
          $ python batch_rw.py XXXX search_under_age 2
          $ python batch_rw.py XXXX search_under_age 2
          +
          sh
          $ python batch_rw.py XXXX search_under_age 2
          $ python batch_rw.py XXXX search_under_age 2

          上の 2 つのコマンドを何回か繰り返し実行してみて,データベースに負荷をかけてみよう. とくに大きな遅延なく結果が返ってくることが確認できるだろう.

          スタックの削除

          DynamoDB で十分に遊ぶことができたら,忘れずにスタックを削除しよう.

          これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

          -
          sh
          $ cdk destroy
          $ cdk destroy
          +
          sh
          $ cdk destroy
          $ cdk destroy

          S3 ハンズオン

          最後に, S3 の簡単なチュートリアルを紹介する. ハンズオンのソースコードは GitHub の handson/serverless/s3 に置いてある.

          figure_title が今回提供する S3 チュートリアルの概要である. STEP 1 として, AWS CDK を用いて S3 に新しい空のバケット (Bucket) を作成する. 続いて STEP 2 では,データのアップロード・ダウンロードの方法を解説する.

          S3 チュートリアルの概要

          このハンズオンは,基本的に S3 の無料枠 の範囲内で実行することができる.

          app.py にデプロイするプログラムが書かれている. 中身を見てみよう.

          -
          python
          class SimpleS3(core.Stack):
          -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
          -        super().__init__(scope, name, **kwargs)
          +
          python
          class SimpleS3(core.Stack):
          +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
          +        super().__init__(scope, name, **kwargs)
           
          -        # S3 bucket to store data
          -        bucket = s3.Bucket(
          -            self, "bucket",
          -            removal_policy=core.RemovalPolicy.DESTROY,
          -            auto_delete_objects=True,
          -        )
          class SimpleS3(core.Stack):
          -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
          -        super().__init__(scope, name, **kwargs)
          +        # S3 bucket to store data
          +        bucket = s3.Bucket(
          +            self, "bucket",
          +            removal_policy=core.RemovalPolicy.DESTROY,
          +            auto_delete_objects=True,
          +        )
          class SimpleS3(core.Stack):
          +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
          +        super().__init__(scope, name, **kwargs)
           
          -        # S3 bucket to store data
          -        bucket = s3.Bucket(
          -            self, "bucket",
          -            removal_policy=core.RemovalPolicy.DESTROY,
          -            auto_delete_objects=True,
          -        )
          + # S3 bucket to store data + bucket = s3.Bucket( + self, "bucket", + removal_policy=core.RemovalPolicy.DESTROY, + auto_delete_objects=True, + )

          s3.Bucket() を呼ぶことによって空のバケットが新規に作成される. 上記のコードだと,バケットの名前は自動生成される. もし,自分の指定した名前を与えたい場合は, bucket_name というパラメータを指定すればよい. その際, バケットの名前はユニークでなければならない (i.e. AWS のデプロイが行われるリージョン内で名前の重複がない) 点に注意しよう. もし,同じ名前のバケットが既に存在する場合はエラーが返ってくる.

          デフォルトでは, CloudFormation スタックが削除されたとき, S3 バケットとその中に保存されたファイルは削除されない. これは,大切なデータを誤って消してしまうことを防止するための安全策である. cdk destroy を実行したときにバケットも含めてすべて削除されるようにするには, removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True とパラメータを設定する. 結果もよく理解したうえで,自分の用途にあった適切なパラメータを設定しよう.

          デプロイ

          デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

          -
          sh
          # プロジェクトのディレクトリに移動
          -$ cd handson/serverless/s3
          +
          sh
          # プロジェクトのディレクトリに移動
          +$ cd handson/serverless/s3
           
          -# venv を作成し,依存ライブラリのインストールを行う
          -$ python3 -m venv .env
          -$ source .env/bin/activate
          -$ pip install -r requirements.txt
          +# venv を作成し,依存ライブラリのインストールを行う
          +$ python3 -m venv .env
          +$ source .env/bin/activate
          +$ pip install -r requirements.txt
           
          -# デプロイを実行
          -$ cdk deploy
          # プロジェクトのディレクトリに移動
          -$ cd handson/serverless/s3
          +# デプロイを実行
          +$ cdk deploy
          # プロジェクトのディレクトリに移動
          +$ cd handson/serverless/s3
           
          -# venv を作成し,依存ライブラリのインストールを行う
          -$ python3 -m venv .env
          -$ source .env/bin/activate
          -$ pip install -r requirements.txt
          +# venv を作成し,依存ライブラリのインストールを行う
          +$ python3 -m venv .env
          +$ source .env/bin/activate
          +$ pip install -r requirements.txt
           
          -# デプロイを実行
          -$ cdk deploy
          +# デプロイを実行 +$ cdk deploy

          デプロイを実行すると, figure_title のような出力が得られるはずである. ここで表示されている SimpleS3.BucketName = XXXX が,新しく作られたバケットの名前である (今回提供しているコードを使うとランダムな名前がバケットに割り当てられる). これはあとで使うのでメモしておこう.

          デプロイ実行後の出力

          データの読み書き

          スタックのデプロイが完了したら,早速バケットにデータをアップロードしてみよう.

          まずは,以下のコマンドを実行して, tmp.txt という仮のファイルを生成する.

          -
          sh
          $ echo "Hello world!" >> tmp.txt
          $ echo "Hello world!" >> tmp.txt
          +
          sh
          $ echo "Hello world!" >> tmp.txt
          $ echo "Hello world!" >> tmp.txt

          ハンズオンのディレクトリにある simple_s3.pyboto3 ライブラリを使用した S3 のファイルのアップロード・ダウンロードのスクリプトが書いてある. simple_s3.py を使って,上で作成した tmp.txt を以下のコマンドによりバケットにアップロードする. XXXX のところは,自分自身のバケットの名前で置き換えること.

          -
          sh
          $ python simple_s3.py XXXX upload tmp.txt
          $ python simple_s3.py XXXX upload tmp.txt
          +
          sh
          $ python simple_s3.py XXXX upload tmp.txt
          $ python simple_s3.py XXXX upload tmp.txt

          simple_s3.py のアップロードを担当している部分を以下に抜粋する.

          -
          python
          def upload_file(bucket_name, filename, key=None):
          -    bucket = s3.Bucket(bucket_name)
          +
          python
          def upload_file(bucket_name, filename, key=None):
          +    bucket = s3.Bucket(bucket_name)
           
          -    if key is None:
          -        key = os.path.basename(filename)
          +    if key is None:
          +        key = os.path.basename(filename)
           
          -    bucket.upload_file(filename, key)
          def upload_file(bucket_name, filename, key=None):
          -    bucket = s3.Bucket(bucket_name)
          +    bucket.upload_file(filename, key)
          def upload_file(bucket_name, filename, key=None):
          +    bucket = s3.Bucket(bucket_name)
           
          -    if key is None:
          -        key = os.path.basename(filename)
          +    if key is None:
          +        key = os.path.basename(filename)
           
          -    bucket.upload_file(filename, key)
          + bucket.upload_file(filename, key)

          bucket = s3.Bucket(bucket_name) の行で Bucket() オブジェクトを呼び出している. そして, upload_file() メソッドを呼ぶことでファイルのアップロードを実行している.

          S3 においてファイルの識別子として使われるのが Key である. これは,従来的なファイルシステムにおけるパス (Path) と相同な概念で,それぞれのファイルに固有な Key が割り当てられる必要がある. Key という呼び方は, S3 が Object storage と呼ばれるシステムに立脚していることに由来する. --key のオプションを追加して simple_s3.py を実行することで, Key を指定してアップロードを実行することができる.

          -
          sh
          $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
          $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
          +
          sh
          $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt
          $ python simple_s3.py XXXX upload tmp.txt --key a/b/tmp.txt

          ここではアップロードされたファイルに a/b/tmp.txt という Key を割り当てている.

          ここまでコマンドを実行し終えたところで,一度 AWS コンソールに行き S3 の中身を確認してみよう. S3 のコンソールに行くと,バケットの一覧が見つかるはずである. その中から, simples3-bucket から始まるランダムな名前のついたバケットを探し,クリックする. するとバケットの中に含まれるファイルの一覧が表示される (figure_title).

          S3 バケットの中のファイル一覧

          ここで実行した 2 つのコマンドによって, tmp.txt というファイルと, a/b/tmp.txt というファイルが見つかることに注目しよう. 従来的なファイルシステムと似た体験を提供するため, S3 では Key が "/" (スラッシュ) によって区切られていた場合,ツリー状の階層構造によってファイルを管理することができる.

          オブジェクトストレージには本来ディレクトリという概念はない. 上で紹介した "/" による階層づけはあくまでユーザー体験向上の目的のお化粧的な機能である.

          次に,バケットからファイルのダウンロードを実行してみよう. simple_s3.py を使って,以下のコマンドを実行すればよい. XXXX のところは,自分自身のバケットの名前で置き換えること.

          -
          sh
          $ python simple_s3.py XXXX download tmp.txt
          $ python simple_s3.py XXXX download tmp.txt
          +
          sh
          $ python simple_s3.py XXXX download tmp.txt
          $ python simple_s3.py XXXX download tmp.txt

          simple_s3.py のダウンロードを担当している部分を以下に抜粋する.

          -
          python
          def download_file(bucket_name, key, filename=None):
          -    bucket = s3.Bucket(bucket_name)
          +
          python
          def download_file(bucket_name, key, filename=None):
          +    bucket = s3.Bucket(bucket_name)
           
          -    if filename is None:
          -        filename = os.path.basename(key)
          +    if filename is None:
          +        filename = os.path.basename(key)
           
          -    bucket.download_file(key, filename)
          def download_file(bucket_name, key, filename=None):
          -    bucket = s3.Bucket(bucket_name)
          +    bucket.download_file(key, filename)
          def download_file(bucket_name, key, filename=None):
          +    bucket = s3.Bucket(bucket_name)
           
          -    if filename is None:
          -        filename = os.path.basename(key)
          +    if filename is None:
          +        filename = os.path.basename(key)
           
          -    bucket.download_file(key, filename)
          + bucket.download_file(key, filename)

          S3 からのダウンロードはシンプルで, download_file() メソッドを使って,ダウンロードしたい対象の Key を指定すればよい. ローカルのコンピュータでの保存先のパスを 2 個目の引数として渡している.

          スタックの削除

          以上のハンズオンで, S3 の一番基本的な使い方を紹介した. ここまでのハンズオンが理解できたら,忘れずにスタックを削除しよう. これまでのハンズオンと同様,スタックを削除するには,次のコマンドを実行すればよい.

          -
          sh
          $ cdk destroy
          $ cdk destroy
          +
          sh
          $ cdk destroy
          $ cdk destroy

          Hands-on #6: Bashoutter

          さて,最後のハンズオンとなる第六回では,これまで学んできたサーバーレスクラウドの技術を使って,簡単なウェブサービスを作ってみよう. 具体的には,人々が自分の作った俳句を投稿する SNS サービス (Bashoutter と名付ける) を作成してみよう. Lambda, DynamoDB, S3 などの技術をすべて盛り込み,シンプルながらもサーバーレスの利点を生かしたスケーラブルな SNS アプリが誕生する. 最終的には, figure_title のような,ミニマルではあるがとても現代風な SNS サイトが完成する!

          ハンズオン#6で作製する SNS アプリケーション "Bashoutter"

          @@ -37402,197 +37402,197 @@ output = json

        それでは,プログラムのソースコードを見てみよう (handson/bashoutter/app.py).

        -
        python
        class Bashoutter(core.Stack):
        +
        python
        class Bashoutter(core.Stack):
         
        -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
        -        super().__init__(scope, name, **kwargs)
        +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
        +        super().__init__(scope, name, **kwargs)
         
        -        #
        -        # dynamoDB table to store haiku
        -        table = ddb.Table(
        -            self, "Bashoutter-Table",
        -            partition_key=ddb.Attribute(
        -                name="item_id",
        -                type=ddb.AttributeType.STRING
        -            ),
        -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
        -            removal_policy=core.RemovalPolicy.DESTROY
        -        )
        +        #
        +        # dynamoDB table to store haiku
        +        table = ddb.Table(
        +            self, "Bashoutter-Table",
        +            partition_key=ddb.Attribute(
        +                name="item_id",
        +                type=ddb.AttributeType.STRING
        +            ),
        +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
        +            removal_policy=core.RemovalPolicy.DESTROY
        +        )
         
        -        #
        -        bucket = s3.Bucket(
        -            self, "Bashoutter-Bucket",
        -            website_index_document="index.html",
        -            public_read_access=True,
        -            removal_policy=core.RemovalPolicy.DESTROY
        -        )
        +        #
        +        bucket = s3.Bucket(
        +            self, "Bashoutter-Bucket",
        +            website_index_document="index.html",
        +            public_read_access=True,
        +            removal_policy=core.RemovalPolicy.DESTROY
        +        )
         
        -        common_params = {
        -            "runtime": _lambda.Runtime.PYTHON_3_7,
        -            "environment": {
        -                "TABLE_NAME": table.table_name
        -            }
        -        }
        +        common_params = {
        +            "runtime": _lambda.Runtime.PYTHON_3_7,
        +            "environment": {
        +                "TABLE_NAME": table.table_name
        +            }
        +        }
         
        -        #
        -        # define Lambda functions
        -        get_haiku_lambda = _lambda.Function(
        -            self, "GetHaiku",
        -            code=_lambda.Code.from_asset("api"),
        -            handler="api.get_haiku",
        -            memory_size=512,
        -            **common_params,
        -        )
        -        post_haiku_lambda = _lambda.Function(
        -            self, "PostHaiku",
        -            code=_lambda.Code.from_asset("api"),
        -            handler="api.post_haiku",
        -            **common_params,
        -        )
        -        patch_haiku_lambda = _lambda.Function(
        -            self, "PatchHaiku",
        -            code=_lambda.Code.from_asset("api"),
        -            handler="api.patch_haiku",
        -            **common_params,
        -        )
        -        delete_haiku_lambda = _lambda.Function(
        -            self, "DeleteHaiku",
        -            code=_lambda.Code.from_asset("api"),
        -            handler="api.delete_haiku",
        -            **common_params,
        -        )
        +        #
        +        # define Lambda functions
        +        get_haiku_lambda = _lambda.Function(
        +            self, "GetHaiku",
        +            code=_lambda.Code.from_asset("api"),
        +            handler="api.get_haiku",
        +            memory_size=512,
        +            **common_params,
        +        )
        +        post_haiku_lambda = _lambda.Function(
        +            self, "PostHaiku",
        +            code=_lambda.Code.from_asset("api"),
        +            handler="api.post_haiku",
        +            **common_params,
        +        )
        +        patch_haiku_lambda = _lambda.Function(
        +            self, "PatchHaiku",
        +            code=_lambda.Code.from_asset("api"),
        +            handler="api.patch_haiku",
        +            **common_params,
        +        )
        +        delete_haiku_lambda = _lambda.Function(
        +            self, "DeleteHaiku",
        +            code=_lambda.Code.from_asset("api"),
        +            handler="api.delete_haiku",
        +            **common_params,
        +        )
         
        -        #
        -        # grant permissions
        -        table.grant_read_data(get_haiku_lambda)
        -        table.grant_read_write_data(post_haiku_lambda)
        -        table.grant_read_write_data(patch_haiku_lambda)
        -        table.grant_read_write_data(delete_haiku_lambda)
        +        #
        +        # grant permissions
        +        table.grant_read_data(get_haiku_lambda)
        +        table.grant_read_write_data(post_haiku_lambda)
        +        table.grant_read_write_data(patch_haiku_lambda)
        +        table.grant_read_write_data(delete_haiku_lambda)
         
        -        #
        -        # define API Gateway
        -        api = apigw.RestApi(
        -            self, "BashoutterApi",
        -            default_cors_preflight_options=apigw.CorsOptions(
        -                allow_origins=apigw.Cors.ALL_ORIGINS,
        -                allow_methods=apigw.Cors.ALL_METHODS,
        -            )
        -        )
        +        #
        +        # define API Gateway
        +        api = apigw.RestApi(
        +            self, "BashoutterApi",
        +            default_cors_preflight_options=apigw.CorsOptions(
        +                allow_origins=apigw.Cors.ALL_ORIGINS,
        +                allow_methods=apigw.Cors.ALL_METHODS,
        +            )
        +        )
         
        -        haiku = api.root.add_resource("haiku")
        -        haiku.add_method(
        -            "GET",
        -            apigw.LambdaIntegration(get_haiku_lambda)
        -        )
        -        haiku.add_method(
        -            "POST",
        -            apigw.LambdaIntegration(post_haiku_lambda)
        -        )
        +        haiku = api.root.add_resource("haiku")
        +        haiku.add_method(
        +            "GET",
        +            apigw.LambdaIntegration(get_haiku_lambda)
        +        )
        +        haiku.add_method(
        +            "POST",
        +            apigw.LambdaIntegration(post_haiku_lambda)
        +        )
         
        -        haiku_item_id = haiku.add_resource("{item_id}")
        -        haiku_item_id.add_method(
        -            "PATCH",
        -            apigw.LambdaIntegration(patch_haiku_lambda)
        -        )
        -        haiku_item_id.add_method(
        -            "DELETE",
        -            apigw.LambdaIntegration(delete_haiku_lambda)
        -        )
        class Bashoutter(core.Stack):
        +        haiku_item_id = haiku.add_resource("{item_id}")
        +        haiku_item_id.add_method(
        +            "PATCH",
        +            apigw.LambdaIntegration(patch_haiku_lambda)
        +        )
        +        haiku_item_id.add_method(
        +            "DELETE",
        +            apigw.LambdaIntegration(delete_haiku_lambda)
        +        )
        class Bashoutter(core.Stack):
         
        -    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
        -        super().__init__(scope, name, **kwargs)
        +    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
        +        super().__init__(scope, name, **kwargs)
         
        -        #
        -        # dynamoDB table to store haiku
        -        table = ddb.Table(
        -            self, "Bashoutter-Table",
        -            partition_key=ddb.Attribute(
        -                name="item_id",
        -                type=ddb.AttributeType.STRING
        -            ),
        -            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
        -            removal_policy=core.RemovalPolicy.DESTROY
        -        )
        +        #
        +        # dynamoDB table to store haiku
        +        table = ddb.Table(
        +            self, "Bashoutter-Table",
        +            partition_key=ddb.Attribute(
        +                name="item_id",
        +                type=ddb.AttributeType.STRING
        +            ),
        +            billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
        +            removal_policy=core.RemovalPolicy.DESTROY
        +        )
         
        -        #
        -        bucket = s3.Bucket(
        -            self, "Bashoutter-Bucket",
        -            website_index_document="index.html",
        -            public_read_access=True,
        -            removal_policy=core.RemovalPolicy.DESTROY
        -        )
        +        #
        +        bucket = s3.Bucket(
        +            self, "Bashoutter-Bucket",
        +            website_index_document="index.html",
        +            public_read_access=True,
        +            removal_policy=core.RemovalPolicy.DESTROY
        +        )
         
        -        common_params = {
        -            "runtime": _lambda.Runtime.PYTHON_3_7,
        -            "environment": {
        -                "TABLE_NAME": table.table_name
        -            }
        -        }
        +        common_params = {
        +            "runtime": _lambda.Runtime.PYTHON_3_7,
        +            "environment": {
        +                "TABLE_NAME": table.table_name
        +            }
        +        }
         
        -        #
        -        # define Lambda functions
        -        get_haiku_lambda = _lambda.Function(
        -            self, "GetHaiku",
        -            code=_lambda.Code.from_asset("api"),
        -            handler="api.get_haiku",
        -            memory_size=512,
        -            **common_params,
        -        )
        -        post_haiku_lambda = _lambda.Function(
        -            self, "PostHaiku",
        -            code=_lambda.Code.from_asset("api"),
        -            handler="api.post_haiku",
        -            **common_params,
        -        )
        -        patch_haiku_lambda = _lambda.Function(
        -            self, "PatchHaiku",
        -            code=_lambda.Code.from_asset("api"),
        -            handler="api.patch_haiku",
        -            **common_params,
        -        )
        -        delete_haiku_lambda = _lambda.Function(
        -            self, "DeleteHaiku",
        -            code=_lambda.Code.from_asset("api"),
        -            handler="api.delete_haiku",
        -            **common_params,
        -        )
        +        #
        +        # define Lambda functions
        +        get_haiku_lambda = _lambda.Function(
        +            self, "GetHaiku",
        +            code=_lambda.Code.from_asset("api"),
        +            handler="api.get_haiku",
        +            memory_size=512,
        +            **common_params,
        +        )
        +        post_haiku_lambda = _lambda.Function(
        +            self, "PostHaiku",
        +            code=_lambda.Code.from_asset("api"),
        +            handler="api.post_haiku",
        +            **common_params,
        +        )
        +        patch_haiku_lambda = _lambda.Function(
        +            self, "PatchHaiku",
        +            code=_lambda.Code.from_asset("api"),
        +            handler="api.patch_haiku",
        +            **common_params,
        +        )
        +        delete_haiku_lambda = _lambda.Function(
        +            self, "DeleteHaiku",
        +            code=_lambda.Code.from_asset("api"),
        +            handler="api.delete_haiku",
        +            **common_params,
        +        )
         
        -        #
        -        # grant permissions
        -        table.grant_read_data(get_haiku_lambda)
        -        table.grant_read_write_data(post_haiku_lambda)
        -        table.grant_read_write_data(patch_haiku_lambda)
        -        table.grant_read_write_data(delete_haiku_lambda)
        +        #
        +        # grant permissions
        +        table.grant_read_data(get_haiku_lambda)
        +        table.grant_read_write_data(post_haiku_lambda)
        +        table.grant_read_write_data(patch_haiku_lambda)
        +        table.grant_read_write_data(delete_haiku_lambda)
         
        -        #
        -        # define API Gateway
        -        api = apigw.RestApi(
        -            self, "BashoutterApi",
        -            default_cors_preflight_options=apigw.CorsOptions(
        -                allow_origins=apigw.Cors.ALL_ORIGINS,
        -                allow_methods=apigw.Cors.ALL_METHODS,
        -            )
        -        )
        +        #
        +        # define API Gateway
        +        api = apigw.RestApi(
        +            self, "BashoutterApi",
        +            default_cors_preflight_options=apigw.CorsOptions(
        +                allow_origins=apigw.Cors.ALL_ORIGINS,
        +                allow_methods=apigw.Cors.ALL_METHODS,
        +            )
        +        )
         
        -        haiku = api.root.add_resource("haiku")
        -        haiku.add_method(
        -            "GET",
        -            apigw.LambdaIntegration(get_haiku_lambda)
        -        )
        -        haiku.add_method(
        -            "POST",
        -            apigw.LambdaIntegration(post_haiku_lambda)
        -        )
        +        haiku = api.root.add_resource("haiku")
        +        haiku.add_method(
        +            "GET",
        +            apigw.LambdaIntegration(get_haiku_lambda)
        +        )
        +        haiku.add_method(
        +            "POST",
        +            apigw.LambdaIntegration(post_haiku_lambda)
        +        )
         
        -        haiku_item_id = haiku.add_resource("{item_id}")
        -        haiku_item_id.add_method(
        -            "PATCH",
        -            apigw.LambdaIntegration(patch_haiku_lambda)
        -        )
        -        haiku_item_id.add_method(
        -            "DELETE",
        -            apigw.LambdaIntegration(delete_haiku_lambda)
        -        )
        + haiku_item_id = haiku.add_resource("{item_id}") + haiku_item_id.add_method( + "PATCH", + apigw.LambdaIntegration(patch_haiku_lambda) + ) + haiku_item_id.add_method( + "DELETE", + apigw.LambdaIntegration(delete_haiku_lambda) + )
        • ここで,俳句の情報を記録しておくための DynamoDB テーブルを定義している.

          @@ -37613,17 +37613,17 @@ output = json

          それぞれの項目について,もう少し詳しく説明しよう.

          Public access mode の S3 バケット

          S3 のバケットを作成しているコードを見てみよう.

          -
          python
          bucket = s3.Bucket(
          -    self, "Bashoutter-Bucket",
          -    website_index_document="index.html",
          -    public_read_access=True,
          -    removal_policy=core.RemovalPolicy.DESTROY
          -)
          bucket = s3.Bucket(
          -    self, "Bashoutter-Bucket",
          -    website_index_document="index.html",
          -    public_read_access=True,
          -    removal_policy=core.RemovalPolicy.DESTROY
          -)
          +
          python
          bucket = s3.Bucket(
          +    self, "Bashoutter-Bucket",
          +    website_index_document="index.html",
          +    public_read_access=True,
          +    removal_policy=core.RemovalPolicy.DESTROY
          +)
          bucket = s3.Bucket(
          +    self, "Bashoutter-Bucket",
          +    website_index_document="index.html",
          +    public_read_access=True,
          +    removal_policy=core.RemovalPolicy.DESTROY
          +)

          ここで注目してほしいのは public_read_access=True の部分だ. 前章で, S3 について説明を行ったときには触れなかったが, S3 には Public access mode という機能がある. Public access mode をオンにしておくと,バケットの中のファイルは認証なしで (i.e. インターネット上の誰でも) 閲覧できるようになる. この設定は,一般公開されているウェブサイトの静的なコンテンツを置いておくのに最適であり,多くのサーバーレスによるウェブサービスでこのような設計が行われる. public access mode を設定しておくと, http://XXXX.s3-website-ap-northeast-1.amazonaws.com/ のような固有の URL がバケットに対して付与される. そして,クライアントがこの URL にアクセスをすると,バケットの中にある index.html がクライアントに返され,ページがロードされる (どのファイルが返されるかは, website_index_document="index.html" の部分で設定している.)

          なお,この時点ではバケットは空である. HTML/CSS/JS など静的コンテンツの配置は,デプロイを行った後ほどのステップで行う.

          より本格的なウェブページを運用する際には, public access mode の S3 バケットに, CloudFront という機能を追加することが一般的である. CloudFront により, Content Delivery Nework (CDN) や暗号化された HTTPS 通信を設定することができる. CloudFront についての詳細は 公式ドキュメンテーション "What is Amazon CloudFront?" などを参照いただきたい.

          @@ -37634,72 +37634,72 @@ output = json

          今回の S3 バケットには, AWS によって付与されたランダムな URL がついている. これを. example.com のような自分のドメインでホストしたければ, AWS によって付与された URL を自分のドメインの DNS レコードに追加すればよい.

          API のハンドラ関数

          API リクエストが来たときに,リクエストされた処理を行う関数のことをハンドラ (handler) 関数とよぶ. GET /haiku の API に対してのハンドラ関数を Lambda で定義している部分を見てみよう.

          -
          python
          get_haiku_lambda = _lambda.Function(
          -    self, "GetHaiku",
          -    code=_lambda.Code.from_asset("api"),
          -    handler="api.get_haiku",
          -    memory_size=512,
          -    **common_params
          -)
          get_haiku_lambda = _lambda.Function(
          -    self, "GetHaiku",
          -    code=_lambda.Code.from_asset("api"),
          -    handler="api.get_haiku",
          -    memory_size=512,
          -    **common_params
          -)
          +
          python
          get_haiku_lambda = _lambda.Function(
          +    self, "GetHaiku",
          +    code=_lambda.Code.from_asset("api"),
          +    handler="api.get_haiku",
          +    memory_size=512,
          +    **common_params
          +)
          get_haiku_lambda = _lambda.Function(
          +    self, "GetHaiku",
          +    code=_lambda.Code.from_asset("api"),
          +    handler="api.get_haiku",
          +    memory_size=512,
          +    **common_params
          +)

          簡単なところから見ていくと, memory_size=512 の箇所でメモリーの使用量を 512MB に指定している. また, code=_lambda.Code.from_asset("api") によって外部のディレクトリ (api/) を参照せよと指定しており, handler="api.get_haiku" のところで api.py というファイルの get_haiku() という関数をハンドラ関数として実行せよ,と定義している.

          次に,ハンドラ関数として使用されている get_haiku() のコードを見てみよう (handson/bashoutter/api/api.py).

          -
          python
          ddb = boto3.resource("dynamodb")
          -table = ddb.Table(os.environ["TABLE_NAME"])
          +
          python
          ddb = boto3.resource("dynamodb")
          +table = ddb.Table(os.environ["TABLE_NAME"])
           
          -def get_haiku(event, context):
          -    """
          -    handler for GET /haiku
          -    """
          -    try:
          -        response = table.scan()
          +def get_haiku(event, context):
          +    """
          +    handler for GET /haiku
          +    """
          +    try:
          +        response = table.scan()
           
          -        status_code = 200
          -        resp = response.get("Items")
          -    except Exception as e:
          -        status_code = 500
          -        resp = {"description": f"Internal server error. {str(e)}"}
          -    return {
          -        "statusCode": status_code,
          -        "headers": HEADERS,
          -        "body": json.dumps(resp, cls=DecimalEncoder)
          -    }
          ddb = boto3.resource("dynamodb")
          -table = ddb.Table(os.environ["TABLE_NAME"])
          +        status_code = 200
          +        resp = response.get("Items")
          +    except Exception as e:
          +        status_code = 500
          +        resp = {"description": f"Internal server error. {str(e)}"}
          +    return {
          +        "statusCode": status_code,
          +        "headers": HEADERS,
          +        "body": json.dumps(resp, cls=DecimalEncoder)
          +    }
          ddb = boto3.resource("dynamodb")
          +table = ddb.Table(os.environ["TABLE_NAME"])
           
          -def get_haiku(event, context):
          -    """
          -    handler for GET /haiku
          -    """
          -    try:
          -        response = table.scan()
          +def get_haiku(event, context):
          +    """
          +    handler for GET /haiku
          +    """
          +    try:
          +        response = table.scan()
           
          -        status_code = 200
          -        resp = response.get("Items")
          -    except Exception as e:
          -        status_code = 500
          -        resp = {"description": f"Internal server error. {str(e)}"}
          -    return {
          -        "statusCode": status_code,
          -        "headers": HEADERS,
          -        "body": json.dumps(resp, cls=DecimalEncoder)
          -    }
          + status_code = 200 + resp = response.get("Items") + except Exception as e: + status_code = 500 + resp = {"description": f"Internal server error. {str(e)}"} + return { + "statusCode": status_code, + "headers": HEADERS, + "body": json.dumps(resp, cls=DecimalEncoder) + }

          response = table.scan() で,俳句の格納された DynamoDB テーブルから,すべての要素を取り出している. もしなにもエラーが起きなければステータスコード 200 が返され,もしなにかエラーが起こればステータスコード 500 が返されるようになっている.

          上記のような操作を,ほかの API についても繰り返すことで,すべての API のハンドラ関数が定義されている.

          GET /haiku のハンドラ関数で, response = table.scan() という部分があるが,実はこれは最善の書き方ではない. DynamoDB の scan() メソッドは,最大で 1MB までのデータしか返さない. データベースのサイズが大きく, 1MB 以上のデータがある場合には,再帰的に scan() メソッドをよぶ必要がある. 詳しくは boto3 ドキュメンテーション を参照.

          AWS における権限の管理 (IAM)

          以下の部分のコードに注目してほしい.

          -
          python
          table.grant_read_data(get_haiku_lambda)
          -table.grant_read_write_data(post_haiku_lambda)
          -table.grant_read_write_data(patch_haiku_lambda)
          -table.grant_read_write_data(delete_haiku_lambda)
          table.grant_read_data(get_haiku_lambda)
          -table.grant_read_write_data(post_haiku_lambda)
          -table.grant_read_write_data(patch_haiku_lambda)
          -table.grant_read_write_data(delete_haiku_lambda)
          +
          python
          table.grant_read_data(get_haiku_lambda)
          +table.grant_read_write_data(post_haiku_lambda)
          +table.grant_read_write_data(patch_haiku_lambda)
          +table.grant_read_write_data(delete_haiku_lambda)
          table.grant_read_data(get_haiku_lambda)
          +table.grant_read_write_data(post_haiku_lambda)
          +table.grant_read_write_data(patch_haiku_lambda)
          +table.grant_read_write_data(delete_haiku_lambda)

          これまでは説明の簡略化のためにあえて触れてこなかったが, AWS には IAM (Identity and Access Management) という重要な概念がある. IAM は基本的に,あるリソースがほかのリソースに対してどのような権限をもっているか,を規定するものである. Lambda は,デフォルトの状態ではほかのリソースにアクセスする権限をなにも有していない. したがって, Lambda 関数が DynamoDB のデータを読み書きするためには,それを許可するような IAM が Lambda 関数に付与されていなければならない.

          CDK による dynamodb.Table オブジェクトには grant_read_write_data() という便利なメソッドが備わっており,アクセスを許可したい Lambda 関数を引数としてこのメソッドを呼ぶことで,データベースへの読み書きを許可する IAM を付与することができる. 同様に,CDK の s3.Bucket オブジェクトにも grant_read_write() というメソッドが備わっており,これによってバケットへの読み書きを許可することができる. このメソッドは,実は Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する で AWS Batch によるクラスターを構成した際に使用した. 興味のある読者は振り返ってコードを確認してみよう.

          各リソースに付与する IAM は,必要最低限の権限を与えるにとどめるというのが基本方針である. これにより,セキュリティを向上させるだけでなく,意図していないプログラムからのデータベースへの読み書きを防止するという点で,バグを未然に防ぐことができる.

          @@ -37710,69 +37710,69 @@ output = json

          API Gateway を配置することで,大量 (1 秒間に数千から数万件) の API リクエストに対応することのできるシステムを容易に構築することができる. API Gateway の料金は table_title のように設定されている. また,無料利用枠により,月ごとに 100 万件までのリクエストは 0 円で利用できる.

          API Gateway の利用料金設定 (参照)
          Number of Requests (per month)Price (per million)

          First 333 million

          $4.25

          Next 667 million

          $3.53

          Next 19 billion

          $3.00

          Over 20 billion

          $1.91

          ソースコードの該当箇所を見てみよう.

          -
          python
          #
          -api = apigw.RestApi(
          -    self, "BashoutterApi",
          -    default_cors_preflight_options=apigw.CorsOptions(
          -        allow_origins=apigw.Cors.ALL_ORIGINS,
          -        allow_methods=apigw.Cors.ALL_METHODS,
          -    )
          -)
          +
          python
          #
          +api = apigw.RestApi(
          +    self, "BashoutterApi",
          +    default_cors_preflight_options=apigw.CorsOptions(
          +        allow_origins=apigw.Cors.ALL_ORIGINS,
          +        allow_methods=apigw.Cors.ALL_METHODS,
          +    )
          +)
           
          -#
          -haiku = api.root.add_resource("haiku")
          -#
          -haiku.add_method(
          -    "GET",
          -    apigw.LambdaIntegration(get_haiku_lambda)
          -)
          -haiku.add_method(
          -    "POST",
          -    apigw.LambdaIntegration(post_haiku_lambda)
          -)
          +#
          +haiku = api.root.add_resource("haiku")
          +#
          +haiku.add_method(
          +    "GET",
          +    apigw.LambdaIntegration(get_haiku_lambda)
          +)
          +haiku.add_method(
          +    "POST",
          +    apigw.LambdaIntegration(post_haiku_lambda)
          +)
           
          -#
          -haiku_item_id = haiku.add_resource("{item_id}")
          -#
          -haiku_item_id.add_method(
          -    "PATCH",
          -    apigw.LambdaIntegration(patch_haiku_lambda)
          -)
          -haiku_item_id.add_method(
          -    "DELETE",
          -    apigw.LambdaIntegration(delete_haiku_lambda)
          -)
          #
          -api = apigw.RestApi(
          -    self, "BashoutterApi",
          -    default_cors_preflight_options=apigw.CorsOptions(
          -        allow_origins=apigw.Cors.ALL_ORIGINS,
          -        allow_methods=apigw.Cors.ALL_METHODS,
          -    )
          -)
          +#
          +haiku_item_id = haiku.add_resource("{item_id}")
          +#
          +haiku_item_id.add_method(
          +    "PATCH",
          +    apigw.LambdaIntegration(patch_haiku_lambda)
          +)
          +haiku_item_id.add_method(
          +    "DELETE",
          +    apigw.LambdaIntegration(delete_haiku_lambda)
          +)
          #
          +api = apigw.RestApi(
          +    self, "BashoutterApi",
          +    default_cors_preflight_options=apigw.CorsOptions(
          +        allow_origins=apigw.Cors.ALL_ORIGINS,
          +        allow_methods=apigw.Cors.ALL_METHODS,
          +    )
          +)
           
          -#
          -haiku = api.root.add_resource("haiku")
          -#
          -haiku.add_method(
          -    "GET",
          -    apigw.LambdaIntegration(get_haiku_lambda)
          -)
          -haiku.add_method(
          -    "POST",
          -    apigw.LambdaIntegration(post_haiku_lambda)
          -)
          +#
          +haiku = api.root.add_resource("haiku")
          +#
          +haiku.add_method(
          +    "GET",
          +    apigw.LambdaIntegration(get_haiku_lambda)
          +)
          +haiku.add_method(
          +    "POST",
          +    apigw.LambdaIntegration(post_haiku_lambda)
          +)
           
          -#
          -haiku_item_id = haiku.add_resource("{item_id}")
          -#
          -haiku_item_id.add_method(
          -    "PATCH",
          -    apigw.LambdaIntegration(patch_haiku_lambda)
          -)
          -haiku_item_id.add_method(
          -    "DELETE",
          -    apigw.LambdaIntegration(delete_haiku_lambda)
          -)
          +# +haiku_item_id = haiku.add_resource("{item_id}") +# +haiku_item_id.add_method( + "PATCH", + apigw.LambdaIntegration(patch_haiku_lambda) +) +haiku_item_id.add_method( + "DELETE", + apigw.LambdaIntegration(delete_haiku_lambda) +)
          • 最初に, api = apigw.RestApi() により,空の API Gateway を作成している.

            @@ -37795,25 +37795,25 @@ output = json

            API Gateway で新規 API を作成したとき, default_cors_preflight_options= というパラメータで Cross Origin Resource Sharing (CORS) の設定を行っている. これは,ブラウザで走る Web アプリケーションと API を接続するときに必要な設定である.

            アプリケーションのデプロイ

            アプリケーションの中身が理解できたところで,早速デプロイを行ってみよう. デプロイの手順は,これまでのハンズオンとほとんど共通である. ここでは,コマンドのみ列挙する (# で始まる行はコメントである). シークレットキーの設定も忘れずに (AWS CLI のインストール).

            -
            sh
            # プロジェクトのディレクトリに移動
            -$ cd intro-aws/handson/bashoutter
            +
            sh
            # プロジェクトのディレクトリに移動
            +$ cd intro-aws/handson/bashoutter
             
            -# venv を作成し,依存ライブラリのインストールを行う
            -$ python3 -m venv .env
            -$ source .env/bin/activate
            -$ pip install -r requirements.txt
            +# venv を作成し,依存ライブラリのインストールを行う
            +$ python3 -m venv .env
            +$ source .env/bin/activate
            +$ pip install -r requirements.txt
             
            -# デプロイを実行
            -$ cdk deploy
            # プロジェクトのディレクトリに移動
            -$ cd intro-aws/handson/bashoutter
            +# デプロイを実行
            +$ cdk deploy
            # プロジェクトのディレクトリに移動
            +$ cd intro-aws/handson/bashoutter
             
            -# venv を作成し,依存ライブラリのインストールを行う
            -$ python3 -m venv .env
            -$ source .env/bin/activate
            -$ pip install -r requirements.txt
            +# venv を作成し,依存ライブラリのインストールを行う
            +$ python3 -m venv .env
            +$ source .env/bin/activate
            +$ pip install -r requirements.txt
             
            -# デプロイを実行
            -$ cdk deploy
            +# デプロイを実行 +$ cdk deploy

            デプロイのコマンドが無事に実行されれば, figure_title のような出力が得られるはずである. ここで表示されている Bashoutter.BashoutterApiEndpoint = XXXX, Bashoutter.BucketUrl = YYYY の二つ文字列はあとで使うのでメモしておこう.

            CDKデプロイ実行後の出力

            AWS コンソールにログインして,デプロイされたスタックを確認してみよう. まずは,コンソールから API Gateway のページに行く. すると, figure_title のような画面が表示され,デプロイ済みの API エンドポイントの一覧が確認できる.

            @@ -37829,109 +37829,109 @@ output = json

            それでは,デプロイしたアプリケーションに対し,実際に API リクエストを送信してみよう. まずはコマンドラインから API を送信する演習を行おう. S3 に配置した GUI は一旦おいておく.

            ここではコマンドラインから HTTP API リクエストを送信するためのシンプルな HTTP クライアントである HTTPie を使ってみよう. HTTPie は,スタックをデプロイするときに Python 仮想環境 (venv) を作成したとき,一緒にインストールされている. 念のためインストールがうまくいっているか確認するには,仮想環境を立ち上げたあとコマンドラインに http と打ってみる. ヘルプのメッセージが出力されたら準備 OK である.

            まず,先ほどデプロイを実行したときに得られた API のエンドポイントの URL (Bashoutter.BashoutterApiEndpoint = XXXX で得られた XXXX の文字列) をコマンドラインの変数に設定しておく.

            -
            sh
            $ export ENDPOINT_URL=XXXX
            $ export ENDPOINT_URL=XXXX
            +
            sh
            $ export ENDPOINT_URL=XXXX
            $ export ENDPOINT_URL=XXXX

            次に,俳句の一覧を取得するため, GET /haiku の API を送信してみよう.

            -
            sh
            $ http GET "${ENDPOINT_URL}/haiku"
            $ http GET "${ENDPOINT_URL}/haiku"
            +
            sh
            $ http GET "${ENDPOINT_URL}/haiku"
            $ http GET "${ENDPOINT_URL}/haiku"

            現時点では,まだだれも俳句を投稿していないので,空の配列 ([]) が返ってくる.

            それでは次に, POST /haiku を使って俳句を投稿してみよう.

            -
            sh
            $ http POST "${ENDPOINT_URL}/haiku" \
            -username="松尾芭蕉" \
            -first="閑さや" \
            -second="岩にしみ入る" \
            -third="蝉の声"
            $ http POST "${ENDPOINT_URL}/haiku" \
            -username="松尾芭蕉" \
            -first="閑さや" \
            -second="岩にしみ入る" \
            -third="蝉の声"
            +
            sh
            $ http POST "${ENDPOINT_URL}/haiku" \
            +username="松尾芭蕉" \
            +first="閑さや" \
            +second="岩にしみ入る" \
            +third="蝉の声"
            $ http POST "${ENDPOINT_URL}/haiku" \
            +username="松尾芭蕉" \
            +first="閑さや" \
            +second="岩にしみ入る" \
            +third="蝉の声"

            次のような出力が得られるだろう.

            -
            sh
            HTTP/1.1 201 Created
            -Connection: keep-alive
            -Content-Length: 49
            -Content-Type: application/json
            -....
            -{
            -    "description": "Successfully added a new haiku"
            -}
            HTTP/1.1 201 Created
            -Connection: keep-alive
            -Content-Length: 49
            -Content-Type: application/json
            -....
            -{
            -    "description": "Successfully added a new haiku"
            -}
            +
            sh
            HTTP/1.1 201 Created
            +Connection: keep-alive
            +Content-Length: 49
            +Content-Type: application/json
            +....
            +{
            +    "description": "Successfully added a new haiku"
            +}
            HTTP/1.1 201 Created
            +Connection: keep-alive
            +Content-Length: 49
            +Content-Type: application/json
            +....
            +{
            +    "description": "Successfully added a new haiku"
            +}

            新しい俳句を投稿することに成功したようである. 本当に俳句が追加されたか,再び GET リクエストを呼ぶことで確認してみよう.

            -
            sh
            $ http GET "${ENDPOINT_URL}/haiku"
            +
            sh
            $ http GET "${ENDPOINT_URL}/haiku"
             
            -HTTP/1.1 200 OK
            -Connection: keep-alive
            -Content-Length: 258
            -Content-Type: application/json
            -...
            -[
            -    {
            -        "created_at": "2020-07-06T02:46:04+00:00",
            -        "first": "閑さや",
            -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
            -        "likes": 0.0,
            -        "second": "岩にしみ入る",
            -        "third": "蝉の声",
            -        "username": "松尾芭蕉"
            -    }
            -]
            $ http GET "${ENDPOINT_URL}/haiku"
            +HTTP/1.1 200 OK
            +Connection: keep-alive
            +Content-Length: 258
            +Content-Type: application/json
            +...
            +[
            +    {
            +        "created_at": "2020-07-06T02:46:04+00:00",
            +        "first": "閑さや",
            +        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
            +        "likes": 0.0,
            +        "second": "岩にしみ入る",
            +        "third": "蝉の声",
            +        "username": "松尾芭蕉"
            +    }
            +]
            $ http GET "${ENDPOINT_URL}/haiku"
             
            -HTTP/1.1 200 OK
            -Connection: keep-alive
            -Content-Length: 258
            -Content-Type: application/json
            -...
            -[
            -    {
            -        "created_at": "2020-07-06T02:46:04+00:00",
            -        "first": "閑さや",
            -        "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b",
            -        "likes": 0.0,
            -        "second": "岩にしみ入る",
            -        "third": "蝉の声",
            -        "username": "松尾芭蕉"
            -    }
            -]
            +HTTP/1.1 200 OK +Connection: keep-alive +Content-Length: 258 +Content-Type: application/json +... +[ + { + "created_at": "2020-07-06T02:46:04+00:00", + "first": "閑さや", + "item_id": "7e91c5e4d7ad47909e0ac14c8bbab05b", + "likes": 0.0, + "second": "岩にしみ入る", + "third": "蝉の声", + "username": "松尾芭蕉" + } +]

            素晴らしい!

            次に, PATCH /haiku/{item_id} を呼ぶことでこの俳句にいいねを追加してみよう. 一つ前のコマンドで取得した俳句の item_id を,次のコマンドの XXXX に代入した上で実行しよう.

            -
            sh
            $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
            $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
            +
            sh
            $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"
            $ http PATCH "${ENDPOINT_URL}/haiku/XXXX"

            {"description": "OK"} という出力が得られるはずである. 再び GET リクエストを送ることで,いいね (likes) が 1 増えたことを確認しよう.

            -
            sh
            $ http GET "${ENDPOINT_URL}/haiku"
            -...
            -[
            -    {
            -        ...
            -        "likes": 1.0,
            -        ...
            -    }
            -]
            $ http GET "${ENDPOINT_URL}/haiku"
            -...
            -[
            -    {
            -        ...
            -        "likes": 1.0,
            -        ...
            -    }
            -]
            +
            sh
            $ http GET "${ENDPOINT_URL}/haiku"
            +...
            +[
            +    {
            +        ...
            +        "likes": 1.0,
            +        ...
            +    }
            +]
            $ http GET "${ENDPOINT_URL}/haiku"
            +...
            +[
            +    {
            +        ...
            +        "likes": 1.0,
            +        ...
            +    }
            +]

            最後に, DELETE リクエストを送ることで俳句をデータベースから削除しよう. XXXXitem_id の値で置き換えたうえで次のコマンドを実行する.

            -
            sh
            $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
            $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
            +
            sh
            $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"
            $ http DELETE "${ENDPOINT_URL}/haiku/XXXX"

            再び GET リクエストを送ることで,返り値が空 ([]) になっていることを確認しよう.

            これで,俳句の投稿・取得・削除そしていいねの追加,といった基本的な API がきちんと動作していることが確認できた.

            大量の API リクエストをシミュレートする

            さて,前節ではマニュアルで一つずつ俳句を投稿した. 多数のユーザーがいるような SNS では,1 秒間に数千件以上の投稿がされている. 今回はサーバーレスアーキテクチャを採用したことで,そのような瞬間的な大量アクセスにも容易に対応できるようなシステムが自動的に構築されている. このポイントを実証するため,ここでは大量の API が送信された状況をシミュレートしてみよう.

            handson/bashoutter/client.py に,大量の API リクエストをシミュレートするためのプログラムが書かれている. このプログラムを使用すると, POST /haiku の API リクエストを指定された回数だけ実行することができる.

            テストとして, API を 300 回実行してみよう. 次のコマンドを実行する.

            -
            sh
            $ python client.py $ENDPOINT_URL post_many 300
            $ python client.py $ENDPOINT_URL post_many 300
            +
            sh
            $ python client.py $ENDPOINT_URL post_many 300
            $ python client.py $ENDPOINT_URL post_many 300

            数秒のうちに実行が完了するだろう. これがもし,単一のサーバーからなる API だったとしたら,このような大量のリクエストの処理にはもっと時間がかかっただろう. 最悪の場合には,サーバーダウンにもつながっていたかもしれない. したがって,今回作成したサーバーレスアプリケーションは,とてもシンプルながらも 1 秒間に数百件の処理を行えるような,スケーラブルなクラウドシステムであることがわかる. サーバーレスでクラウドを設計することの利点を垣間見ることができただろうか?

            先述のコマンドにより大量の俳句を投稿するとデータベースに無駄なデータがどんどん溜まってしまう. データベースを完全に空にするには,次のコマンドを使用する.

            -
            sh
            $ python client.py $ENDPOINT_URL clear_database
            $ python client.py $ENDPOINT_URL clear_database
            +
            sh
            $ python client.py $ENDPOINT_URL clear_database
            $ python client.py $ENDPOINT_URL clear_database

            Bashoutter GUI を動かしてみる

            前節ではコマンドラインから API を送信する演習を行った. ウェブアプリケーションでは,これと同じことがウェブブラウザの背後で行われ,ページのコンテンツが表示されている (figure_title 参照). 最後に, API が GUI と統合されるとどうなるのか,見てみよう.

            CDK のコードで, Public access mode の S3 バケットを作成したことを思い出してほしい. 最初のステップとして,ここにウェブサイトのコンテンツをアップロードしよう. ハンズオンのソースコードの中に gui/dist というフォルダが見つかるはずである. ここにはビルド済みのウェブサイトの静的コンテンツ (HTML/CSS/JavaScript) が入っている. AWS CLI のコマンドを使うことでこれらのファイルを S3 にアップロードしよう.

            -
            sh
            $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
            $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
            +
            sh
            $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>
            $ aws s3 cp --recursive ./gui/dist s3://<BUCKET_NAME>

            コマンドを実行する際は, Bashoutter ハンズオンのディレクトリから行うこと (./gui/dist に注目),そして <BUCKET_NAME> にはデプロイした自身のバケットの名前が入る点に注意. 念のため,AWS コンソールにログインし,バケットにファイルがアップロードされている点を確認しておこう.

            なお,今回は GUI の説明はとくに行わないが, Bashoutter のウェブサイトは Vue.jsVuetify という UI フレームワークを使って作成した. Vue を使うことで, Single page application (SPA) の技術でウェブサイトの画面がレンダリングされる. ソースコードは handson/bashoutter/gui のディレクトリの中にあるので,興味のある読者は確認してみるとよい.

            アップトードが完了したところで,続いてデプロイを実行したときにコマンドラインの出力を見直してみよう. Bashoutter.BucketUrl= で与えられた URL が見つかるはずである (figure_title). これは,先述したとおり, Public access mode の S3 バケットの URL である.

            @@ -37943,11 +37943,11 @@ output = json

            これで, Bashoutter プロジェクトが完成した! この SNS は,インターネットを通じて世界のどこからでもアクセスできる状態にある. また, 大量の API リクエストをシミュレートする で見たように,大量のユーザーの同時アクセスによる負荷がかかっても,柔軟にスケールが行われ遅延なく処理を行うことができる. 極めて簡素ながらも,立派なウェブサービスとしてのスペックは満たしているのである!

            Bashoutter アプリを存分に楽しむことができたら,最後に忘れずにスタックを削除しよう.

            コマンドラインからスタックの削除を実行するには,次のコマンドを使う.

            -
            sh
            $ cdk destroy
            $ cdk destroy
            +
            sh
            $ cdk destroy
            $ cdk destroy

            CDK のバージョンによっては S3 のバケットが空でないと, cdk destroy がエラーを出力する場合がある. この場合はスタックを削除する前に, S3 バケットの中身をすべて削除しなければならない.

            コンソールから実行するには, S3 コンソールに行き,バケットの中身を開いたうえで,すべてのファイルを選択し, "Actions" → "Delete" を実行すればよいい.

            コマンドラインから実行するには, 次のコマンドを使う. <BUCKET NAME> のところは,自分の バケットの名前 ("BashoutterBucketXXXX" というパターンの名前がついているはずである) に置き換えることを忘れずに.

            -
            sh
            $ aws s3 rm <BUCKET NAME> --recursive
            $ aws s3 rm <BUCKET NAME> --recursive
            +
            sh
            $ aws s3 rm <BUCKET NAME> --recursive
            $ aws s3 rm <BUCKET NAME> --recursive

            小括

            ここまでが,本書第三部の内容であった.

            第三部では,クラウドの応用として,一般の人に使ってもらうようなウェブアプリケーション・データベースをどのようにして作るのか,という点に焦点を当てて,説明を行った. その中で,従来的なクラウドシステムの設計と,ここ数年の最新の設計方法であるサーバーレスアーキテクチャについて解説した. Hands-on #5: サーバーレス入門 では, AWS でのサーバーレスの実践として, Lambda, S3, DynamoDB のハンズオンを行った. 最後に, Hands-on #6: Bashoutter では,これらの技術を統合することで,完全サーバーレスなウェブアプリケーション "Bashoutter" を作成した.

            @@ -38048,59 +38048,59 @@ output = json

            vocareum から AWS シークレットキーの発行

            AWS CLI のインストール

            読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

            -
            sh
            $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
            -$ unzip awscliv2.zip
            -$ sudo ./aws/install
            $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
            -$ unzip awscliv2.zip
            -$ sudo ./aws/install
            +
            sh
            $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
            +$ unzip awscliv2.zip
            +$ sudo ./aws/install
            $ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
            +$ unzip awscliv2.zip
            +$ sudo ./aws/install

            インストールできたか確認するため,次のコマンドを打ってバージョン情報が出力されることを確認する.

            -
            sh
            $ aws --version
            $ aws --version
            +
            sh
            $ aws --version
            $ aws --version

            インストールができたら,次のコマンドにより初期設定を行う (参照).

            -
            sh
            $ aws configure
            $ aws configure
            +
            sh
            $ aws configure
            $ aws configure

            コマンドを実行すると, AWS Access Key ID, AWS Secret Access Key を入力するよう指示される. シークレットキーの発行については AWS のシークレットキーの作成 を参照. コマンドは加えて,Default region name を訊いてくる. ここには自分の好きな地域 (例えば ap-northeast-1 =東京リージョン) を指定すればよい. 最後の Default output formatjson としておくとよい.

            このコマンドを完了すると, ~/.aws/credentials~/.aws/config という名前のファイルが生成されているはずである. 念のため, cat コマンドを使って中身を確認してみるとよい.

            -
            sh
            $ cat ~/.aws/credentials
            -[default]
            -aws_access_key_id = XXXXXXXXXXXXXXXXXX
            -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
            +
            sh
            $ cat ~/.aws/credentials
            +[default]
            +aws_access_key_id = XXXXXXXXXXXXXXXXXX
            +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
             
            -$ cat ~/.aws/config
            -[profile default]
            -region = ap-northeast-1
            -output = json
            $ cat ~/.aws/credentials
            -[default]
            -aws_access_key_id = XXXXXXXXXXXXXXXXXX
            -aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
            +$ cat ~/.aws/config
            +[profile default]
            +region = ap-northeast-1
            +output = json
            $ cat ~/.aws/credentials
            +[default]
            +aws_access_key_id = XXXXXXXXXXXXXXXXXX
            +aws_secret_access_key = YYYYYYYYYYYYYYYYYYY
             
            -$ cat ~/.aws/config
            -[profile default]
            -region = ap-northeast-1
            -output = json
            +$ cat ~/.aws/config +[profile default] +region = ap-northeast-1 +output = json

            ~/.aws/credentials には認証鍵の情報が, ~/.aws/config には AWS CLI の設定が記録されている.

            デフォルトでは, [default] という名前でプロファイルが保存される. いくつかのプロファイルを使い分けたければ, default の例に従って,たとえば [myprofile] などという名前でプロファイルを追加すればよい.

            AWS CLI でコマンドを打つときに,プロファイルを使い分けるには,

            -
            sh
            $ aws s3 ls --profile myprofile
            $ aws s3 ls --profile myprofile
            +
            sh
            $ aws s3 ls --profile myprofile
            $ aws s3 ls --profile myprofile

            のように, --profile というオプションをつけてコマンドを実行する.

            いちいち --profile オプションをつけるのが面倒だと感じる場合は, AWS_PROFILE という環境変数を設定するとよい.

            -
            sh
            $ export AWS_PROFILE=myprofile
            $ export AWS_PROFILE=myprofile
            +
            sh
            $ export AWS_PROFILE=myprofile
            $ export AWS_PROFILE=myprofile

            あるいは,認証情報などを環境変数に設定するテクニックもある.

            -
            sh
            export AWS_ACCESS_KEY_ID=XXXXXX
            -export AWS_SECRET_ACCESS_KEY=YYYYYY
            -export AWS_DEFAULT_REGION=ap-northeast-1
            export AWS_ACCESS_KEY_ID=XXXXXX
            -export AWS_SECRET_ACCESS_KEY=YYYYYY
            -export AWS_DEFAULT_REGION=ap-northeast-1
            +
            sh
            export AWS_ACCESS_KEY_ID=XXXXXX
            +export AWS_SECRET_ACCESS_KEY=YYYYYY
            +export AWS_DEFAULT_REGION=ap-northeast-1
            export AWS_ACCESS_KEY_ID=XXXXXX
            +export AWS_SECRET_ACCESS_KEY=YYYYYY
            +export AWS_DEFAULT_REGION=ap-northeast-1

            これらの環境変数は, ~/.aws/credentials よりも高い優先度をもつので,環境変数が設定されていればそちらの情報が使用される (参照).

            AWS Educate Starter Accountus-east-1 のリージョンのみ利用可能である (執筆時点での情報). よって, AWS Educate Starter Account を使用している場合は, default region を us-east-1 に設定する必要がある.

            AWS CDK のインストール

            読者のために,執筆時点におけるインストールの手順 (Linux 向け) を簡単に記述する. 将来のバージョンでは変更される可能性があるので,常に 公式のドキュメンテーション で最新の情報をチェックすることを忘れずに.

            Node.js がインストールされていれば,基本的に次のコマンドを実行すればよい.

            -
            sh
            $ sudo npm install -g aws-cdk
            $ sudo npm install -g aws-cdk
            +
            sh
            $ sudo npm install -g aws-cdk
            $ sudo npm install -g aws-cdk

            本書のハンズオンは AWS CDK version 1.100.0 で開発した. CDK は開発途上のライブラリなので,将来的に API が変更される可能性がある. API の変更によりエラーが生じた場合は, version 1.100.0 を使用することを推奨する.

            -
            sh
            $ npm install -g aws-cdk@1.100
            $ npm install -g aws-cdk@1.100
            +
            sh
            $ npm install -g aws-cdk@1.100
            $ npm install -g aws-cdk@1.100

            インストールできたか確認するため,次のコマンドを打って正しくバージョンが表示されることを確認する.

            -
            sh
            $ cdk --version
            $ cdk --version
            +
            sh
            $ cdk --version
            $ cdk --version

            インストールができたら,次のコマンドにより AWS 側の初期設定を行う. これは一度実行すれば OK.

            -
            sh
            $ cdk bootstrap
            $ cdk bootstrap
            +
            sh
            $ cdk bootstrap
            $ cdk bootstrap

            cdk bootstrap を実行するときは,AWS の認証情報とリージョンが正しく設定されていることを確認する. デフォルトでは ~/.aws/config にあるデフォルトのプロファイルが使用される. デフォルト以外のプロファイルを用いるときは AWS CLI のインストール で紹介したテクニックを使って切り替える.

            AWS CDK の認証情報の設定は AWS CLI と基本的に同じである.詳しくは AWS CLI のインストール を参照.

            WSL のインストール

            @@ -38111,15 +38111,15 @@ output = json

            まず最初に, Administrator 権限で PowerShell を起動する (figure_title). 左下の Windows メニューの検索バーに powershell と入力すると, PowerShell のプログラムが見つかるはずである, これを右クリックし、 Run as administrator を選択し起動する.

            管理者権限での PowerShell の起動

            PowerShell が起動したら、次のコマンドを実行する.

            -
            powershell
            dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
            dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
            +
            powershell
            dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
            dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

            実行して、“The operation completed successfully.” と出力されるのを確認する. これで WSL が enable される.

            次に,先ほどと同じ Administrator 権限で開いた PowerShell で次のコマンドを実行する。

            -
            powersh
            dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
            dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
            +
            powersh
            dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
            dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

            実行して, “The operation completed successfully.” と出力されるのを確認する. これが確認出来たら、一度コンピュータを再起動する.

            続いて, Linux kernel update package を次のリンクからダウンロードする. https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

            ダウンロードしたファイルをダブルクリックして実行する. ダイアログに従ってインストールを完了させる.

            そうしたら,再び PowerShell を開き次のコマンドを実行する。

            -
            sh
            wsl --set-default-version 2
            wsl --set-default-version 2
            +
            sh
            wsl --set-default-version 2
            wsl --set-default-version 2

            最後に、自分の好みの Linux distribution をインストールする. ここでは Ubuntu 20.04 をインストールしよう.

            Microsoft store のアプリを起動し,検索バーに Ubuntu と入力する. Ubuntu 20.04 LTS という項目が見つかるはずなので,それを開き, “Get” ボタンをクリックする (figure_title). しばらく待つと, Ubuntu 20.04 のインストールが完了する.

            Microsoft store から Ubuntu 20.04 をインストール

            @@ -38135,33 +38135,33 @@ output = json

            Windows のユーザーは,Docker Desktop をインストールする. その際, WSL 2 が事前にインストールされていなければならない. 詳細は 公式ドキュメンテーション を参照のこと. Docker Desktop をインストールすると, WSL からも docker コマンドが使用できるようになる.

            Linux ユーザー (特に Ubuntu ユーザー) については,インストールの方法はいくつかのアプローチがある. 公式ドキュメンテーション にいくつかのインストールの方法が示されているので,詳しい情報はそちらを参照いただきたい.

            最も簡単な方法は, Docker が公式で提供しているインストールスクリプトを用いる方法である. この場合,次のコマンドを実行することで Docker がインストールされる.

            -
            sh
            $ curl -fsSL https://get.docker.com -o get-docker.sh
            -$ sudo sh get-docker.sh
            $ curl -fsSL https://get.docker.com -o get-docker.sh
            -$ sudo sh get-docker.sh
            +
            sh
            $ curl -fsSL https://get.docker.com -o get-docker.sh
            +$ sudo sh get-docker.sh
            $ curl -fsSL https://get.docker.com -o get-docker.sh
            +$ sudo sh get-docker.sh

            デフォルトのインストールでは, root ユーザーのみが docker コマンドを使用できる設定になっている. 従って,コマンドには毎回 sudo を付け加える必要がある. これが面倒だと感じる場合は,次のステップにより,使用するユーザーを docker というグループに追加する (詳細は 公式ドキュメンテーション "Post-installation steps for Linux" を参照).

            まず最初に, docker という名前にグループを追加する. インストールによっては,既に docker グループが作られている場合もある.

            -
            sh
            $ sudo groupadd docker
            $ sudo groupadd docker
            +
            sh
            $ sudo groupadd docker
            $ sudo groupadd docker

            次に,現在使用しているユーザーを docker グループに加える.

            -
            sh
            $ sudo usermod -aG docker $USER
            $ sudo usermod -aG docker $USER
            +
            sh
            $ sudo usermod -aG docker $USER
            $ sudo usermod -aG docker $USER

            ここまでできたら,一度ログアウトし,再度ログインする. これによって,グループの変更がターミナルのセッションに反映される.

            設定が正しくできているかを確認するため,次のコマンドを実行してみる.

            -
            sh
            $ docker run hello-world
            $ docker run hello-world
            +
            sh
            $ docker run hello-world
            $ docker run hello-world

            sudo なしでコンテナが実行できたならば,設定は完了である.

            Python venv クイックガイド

            他人からもらったプログラムで, numpy や scipy のバージョンが違う!などの理由で,プログラムが動かない,という経験をしたことがある人は多いのではないだろうか. もし,自分の計算機の中に一つしか Python 環境がないとすると,プロジェクトを切り替えるごとに正しいバージョンをインストールし直さなければならず,これは大変な手間である.

            コードのシェアをよりスムーズにするためには,ライブラリのバージョンはプロジェクトごとに管理されるべきである. それを可能にするのが Python 仮想環境とよばれるツールであり, venv, pyenv, conda などがよく使われる.

            そのなかでも, venv は Python に標準搭載されているのでとても便利である. pyenvconda は,別途インストールの必要があるが,それぞれの長所もある.

            venv を使って仮想環境を作成するには,

            -
            sh
            $ python -m venv .env
            $ python -m venv .env
            +
            sh
            $ python -m venv .env
            $ python -m venv .env

            と実行する. これにより .env/ というディレクトリが作られ,このディレクトリに依存するライブラリが保存されることになる.

            この新たな仮想環境を起動するには

            -
            sh
            $ source .env/bin/activate
            $ source .env/bin/activate
            +
            sh
            $ source .env/bin/activate
            $ source .env/bin/activate

            と実行する.

            シェルのプロンプトに (.env) という文字が追加されていることを確認しよう (figure_title). これが, "いまあなたは venv の中にいますよ" というしるしになる.

            venv を起動したときのプロンプト

            仮想環境を起動すると,それ以降実行する pip コマンドは, .env/ 以下にインストールされる.このようにして,プロジェクトごとに使うライブラリのバージョンを切り分けることができる.

            Python では requirements.txt というファイルに依存ライブラリを記述するのが一般的な慣例である.他人からもらったプログラムに, requirements.txt が定義されていれば,

            -
            sh
            $ pip install -r requirements.txt
            $ pip install -r requirements.txt
            +
            sh
            $ pip install -r requirements.txt
            $ pip install -r requirements.txt

            と実行することで,必要なライブラリをインストールし,瞬時に Python 環境を再現することができる.

            venv による仮想環境を保存するディレクトリの名前は任意に選べることができるが, .env という名前を用いるのが一般的である.

            ハンズオン実行用の Docker image の使い方

            @@ -38169,16 +38169,16 @@ output = json

            ハンズオンのいくつかのコマンドは Docker の外 = ローカルマシンのリアル環境で実行されなければならない. それらについてはハンズオンの該当箇所に注意書きとして記してある.

            Docker イメージは Docker Hub においてある. Docker イメージのビルドファイルは GitHub の docker/Dockerfile にある.

            次のコマンドでコンテナを起動する.

            -
            sh
            $ docker run -it tomomano/labc:latest
            $ docker run -it tomomano/labc:latest
            +
            sh
            $ docker run -it tomomano/labc:latest
            $ docker run -it tomomano/labc:latest

            初回にコマンドを実行したときのみ,イメージが Docker Hub からダウンロード (pull) される. 二回目以降はローカルにダウンロードされたイメージが使用される.

            コンテナが起動すると,次のようなインタラクティブシェルが表示されるはずである (起動時に -it のオプションをつけたのがポイントである).

            -
            sh
            root@aws-handson:~/programlisting
            root@aws-handson:~/programlisting
            +
            sh
            root@aws-handson:~/programlisting
            root@aws-handson:~/programlisting

            この状態で ls コマンドを打つと, handson/ というディレクトリがあるはずである. ここに cd する.

            -
            sh
            $ cd handson
            $ cd handson
            +
            sh
            $ cd handson
            $ cd handson

            すると,各ハンズオンごとのディレクトリが見つかるはずである.

            あとは,ハンズオンごとにディレクトリを移動し,ハンズオンごとの virtualenv を作成し,スタックのデプロイを行えばよい (プログラムを実行する など参照). ハンズオンごとに使用する依存ライブラリが異なるので,それぞれのハンズオンごとに virtualenv を作成するという設計になっている.

            AWS の認証情報を設定することも忘れずに. AWS CLI のインストール で記述したように, AWS_ACCESS_KEY_ID などの環境変数を設定するのが簡単な方法である. あるいは,ローカルマシンの ~/.aws/credentials に認証情報が書き込まれているなら,このディレクトリをコンテナにマウントすることで,同じ認証ファイルをコンテナ内部から参照することが可能である. この選択肢を取る場合は,次のコマンドでコンテナを起動する.

            -
            sh
            $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
            $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
            +
            sh
            $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest
            $ docker run -it -v ~/.aws:/root/.aws:ro tomomano/labc:latest

            これにより,ローカルマシンの ~/.aws をコンテナの /root/.aws にマウントすることができる. 最後の :ro は read-only を意味する. 大切な認証ファイルが誤って書き換えられてしまわないように, read-only のフラグをつけることをおすすめする.

            /root/ がコンテナ環境におけるホームディレクトリである. ここで紹介した認証ファイルをマウントするテクニックは, SSH 鍵をコンテナに渡すときなどにも使える.

            ライセンス

            @@ -38502,7 +38502,7 @@ output = json

          • Exceptions apply for functional requirements, such as for Sass partials. A leading underscore informs the Sass compiler a file is only a partial file and should never be generated into a stand alone CSS file.

          Right:

          -
          file-name-with-dashes.en.min.html
          file-name-with-dashes.en.min.html
          +
          file-name-with-dashes.en.min.html
          file-name-with-dashes.en.min.html

          Do not use special characters

          Avoid using non-alphanumeric characters in file names, such as: '*' ':' '\' '/' '<' '>' '|' '"' '!' '?' '[' ']' ';' '=' '+' '&' '£' '$' '' '%' or ','. These characters can have special meaning in programming languages or can cause problems with different operating systems.

          Use lowercase, never uppercase

          @@ -38520,19 +38520,19 @@ output = json

        • File conditions
        • Possible combinations

          -
          description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
          -description.min.js
          -description.en.html
          -description-01.jpg
          -description-02.jpg
          -description-1024x768_2x.jpg
          -description-desk_2x.jpg
          description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
          -description.min.js
          -description.en.html
          -description-01.jpg
          -description-02.jpg
          -description-1024x768_2x.jpg
          -description-desk_2x.jpg
          +
          description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
          +description.min.js
          +description.en.html
          +description-01.jpg
          +description-02.jpg
          +description-1024x768_2x.jpg
          +description-desk_2x.jpg
          description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
          +description.min.js
          +description.en.html
          +description-01.jpg
          +description-02.jpg
          +description-1024x768_2x.jpg
          +description-desk_2x.jpg

          Write description for developers and users

          Don't be afraid to write long informative file names. Few people type a file name manually and most operating systems support 255 characters. But only add information that makes it easy for users and developers to recognize files from one another at a glance. For the description use information such as:

            @@ -38554,17 +38554,17 @@ output = json

          • If people have exactly the same name written in full, you can add a number: firstnamelastname2.

          Right:

          -
          bvandebiezen.jpg
          -shoogenhout.jpg
          -a-very-long-description-with-name-bvdb.jpg
          -asmith.jpg
          -adamsmith.jpg
          -adamsmith2.jpg
          bvandebiezen.jpg
          -shoogenhout.jpg
          -a-very-long-description-with-name-bvdb.jpg
          -asmith.jpg
          -adamsmith.jpg
          -adamsmith2.jpg
          +
          bvandebiezen.jpg
          +shoogenhout.jpg
          +a-very-long-description-with-name-bvdb.jpg
          +asmith.jpg
          +adamsmith.jpg
          +adamsmith2.jpg
          bvandebiezen.jpg
          +shoogenhout.jpg
          +a-very-long-description-with-name-bvdb.jpg
          +asmith.jpg
          +adamsmith.jpg
          +adamsmith2.jpg

          Use two or more digits to distinguish sequential files with the same description

          • Start number with a dash as a delimiter.
          • @@ -38572,23 +38572,23 @@ output = json

          • Numbers may also be placed before the description if needed. A dash will still be used as delimiter with the description.

          Right:

          -
          description-01.jpg
          -description-02.jpg
          -description-03.jpg
          -description-04.jpg
          -
          -01-description.jpg
          -02-description.jpg
          -03-description.jpg
          -04-description.jpg
          description-01.jpg
          -description-02.jpg
          -description-03.jpg
          -description-04.jpg
          -
          -01-description.jpg
          -02-description.jpg
          -03-description.jpg
          -04-description.jpg
          +
          description-01.jpg
          +description-02.jpg
          +description-03.jpg
          +description-04.jpg
          +
          +01-description.jpg
          +02-description.jpg
          +03-description.jpg
          +04-description.jpg
          description-01.jpg
          +description-02.jpg
          +description-03.jpg
          +description-04.jpg
          +
          +01-description.jpg
          +02-description.jpg
          +03-description.jpg
          +04-description.jpg

          Keep dates or date ranges compact and start with year

          • Write dates without delimiters.
          • @@ -38597,13 +38597,13 @@ output = json

          • Use a double dash to separate two dates describing an interval: yyyy--yyyy. Start with the earliest date.

          Right:

          -
          description-20150401.php
          -description-201504.php
          -description-2015.php
          -description-2000--2010.php
          description-20150401.php
          -description-201504.php
          -description-2015.php
          -description-2000--2010.php
          +
          description-20150401.php
          +description-201504.php
          +description-2015.php
          +description-2000--2010.php
          description-20150401.php
          +description-201504.php
          +description-2015.php
          +description-2000--2010.php

          See 'ISO 8601' for further reading.

          Use special modifiers for target devices, image sizes or media queries, and pixel densities.

          Modifiers are inspired by Apple iOS naming conventions. There are some differences. Apple uses '@'as a delimiter for the section indicating higher resolution images, for example '@2x' for retina images. Because '@' is a reserved character and can create problems, we use Bourbon's convention: an underscore. Also, Apple uses a tilde (~) as a delimiter for a section indicating specific devices. Because also a tilde can create problems, we suggest to simply use a dash.

          @@ -38617,21 +38617,21 @@ output = json

        • When both the width and height should not exceed a dimension but the images should keep the original aspect ratio, add a 'max' (maximum) after the amount of pixels.

        Right:

        -
        description_2x.jpg
        -description-lap.jpg
        -description-desk.jpg
        -description-lap_2x.jpg
        -description-palm-1024w_2x.jpg
        -description-iphone5-568h_2x.jpg
        -description-palm-1024x768_2x.jpg
        -description-40max.jpg
        description_2x.jpg
        -description-lap.jpg
        -description-desk.jpg
        -description-lap_2x.jpg
        -description-palm-1024w_2x.jpg
        -description-iphone5-568h_2x.jpg
        -description-palm-1024x768_2x.jpg
        -description-40max.jpg
        +
        description_2x.jpg
        +description-lap.jpg
        +description-desk.jpg
        +description-lap_2x.jpg
        +description-palm-1024w_2x.jpg
        +description-iphone5-568h_2x.jpg
        +description-palm-1024x768_2x.jpg
        +description-40max.jpg
        description_2x.jpg
        +description-lap.jpg
        +description-desk.jpg
        +description-lap_2x.jpg
        +description-palm-1024w_2x.jpg
        +description-iphone5-568h_2x.jpg
        +description-palm-1024x768_2x.jpg
        +description-40max.jpg

        Use version numbers if available

        • Start version with a dash (-) as delimiter.
        • @@ -38640,18 +38640,18 @@ output = json

        • Types, such as 'a' (alpha), 'b' (beta), 'rc1' (release candidate 1) can be added without delimiters.

        Right:

        -
        description-0.5.js
        -description-1.0b.js
        -description-1.0rc1.js
        description-0.5.js
        -description-1.0b.js
        -description-1.0rc1.js
        +
        description-0.5.js
        +description-1.0b.js
        +description-1.0rc1.js
        description-0.5.js
        +description-1.0b.js
        +description-1.0rc1.js

        Add status when needed

        • You can optionally add a file status such as 'draft' and 'published'.
        • Start status with a dash.

        Right:

        -
        description-draft.md
        description-draft.md
        +
        description-draft.md
        description-draft.md

        Add language code only when different languages are available

        • Use a period to separate the language code from the rest of the file name.
        • @@ -38659,9 +38659,9 @@ output = json

        • Only add languages when different languages are available.

        Right:

        -
        description.nl.txt
        -description.en.txt
        description.nl.txt
        -description.en.txt
        +
        description.nl.txt
        +description.en.txt
        description.nl.txt
        +description.en.txt

        Add file conditions just before the file extension

        • The file condition should be the last part, just before the file extension.
        • @@ -38669,9 +38669,9 @@ output = json

        • Use periods (.) as a delimiter for different conditions.

        Right:

        -
        description.min.js
        -description.custom1234.min.js
        description.min.js
        -description.custom1234.min.js
        +
        description.min.js
        +description.custom1234.min.js
        description.min.js
        +description.custom1234.min.js

        Rewrite original file names not following conventions

        It is not preferred to keep file names in it's original format if it doesn't match your file name conventions. But in some cases it is easier to keep the file name untouched. Sometimes you want to easily replace a file with a newer one from the original source in the future.

        ]]> @@ -38688,7 +38688,7 @@ output = json

      • Exceptions apply for functional requirements, such as for Sass partials. A leading underscore informs the Sass compiler a file is only a partial file and should never be generated into a stand alone CSS file.

      Right:

      -
      file-name-with-dashes.en.min.html
      file-name-with-dashes.en.min.html
      +
      file-name-with-dashes.en.min.html
      file-name-with-dashes.en.min.html

      Do not use special characters

      Avoid using non-alphanumeric characters in file names, such as: '*' ':' '\' '/' '<' '>' '|' '"' '!' '?' '[' ']' ';' '=' '+' '&' '£' '$' '' '%' or ','. These characters can have special meaning in programming languages or can cause problems with different operating systems.

      Use lowercase, never uppercase

      @@ -38706,19 +38706,19 @@ output = json

    • File conditions
    • Possible combinations

      -
      description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
      -description.min.js
      -description.en.html
      -description-01.jpg
      -description-02.jpg
      -description-1024x768_2x.jpg
      -description-desk_2x.jpg
      description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
      -description.min.js
      -description.en.html
      -description-01.jpg
      -description-02.jpg
      -description-1024x768_2x.jpg
      -description-desk_2x.jpg
      +
      description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
      +description.min.js
      +description.en.html
      +description-01.jpg
      +description-02.jpg
      +description-1024x768_2x.jpg
      +description-desk_2x.jpg
      description-01-20150102-palm-1.0b-draft.en.min.js /* extreme combination */
      +description.min.js
      +description.en.html
      +description-01.jpg
      +description-02.jpg
      +description-1024x768_2x.jpg
      +description-desk_2x.jpg

      Write description for developers and users

      Don't be afraid to write long informative file names. Few people type a file name manually and most operating systems support 255 characters. But only add information that makes it easy for users and developers to recognize files from one another at a glance. For the description use information such as:

        @@ -38740,17 +38740,17 @@ output = json

      • If people have exactly the same name written in full, you can add a number: firstnamelastname2.

      Right:

      -
      bvandebiezen.jpg
      -shoogenhout.jpg
      -a-very-long-description-with-name-bvdb.jpg
      -asmith.jpg
      -adamsmith.jpg
      -adamsmith2.jpg
      bvandebiezen.jpg
      -shoogenhout.jpg
      -a-very-long-description-with-name-bvdb.jpg
      -asmith.jpg
      -adamsmith.jpg
      -adamsmith2.jpg
      +
      bvandebiezen.jpg
      +shoogenhout.jpg
      +a-very-long-description-with-name-bvdb.jpg
      +asmith.jpg
      +adamsmith.jpg
      +adamsmith2.jpg
      bvandebiezen.jpg
      +shoogenhout.jpg
      +a-very-long-description-with-name-bvdb.jpg
      +asmith.jpg
      +adamsmith.jpg
      +adamsmith2.jpg

      Use two or more digits to distinguish sequential files with the same description

      • Start number with a dash as a delimiter.
      • @@ -38758,23 +38758,23 @@ output = json

      • Numbers may also be placed before the description if needed. A dash will still be used as delimiter with the description.

      Right:

      -
      description-01.jpg
      -description-02.jpg
      -description-03.jpg
      -description-04.jpg
      -
      -01-description.jpg
      -02-description.jpg
      -03-description.jpg
      -04-description.jpg
      description-01.jpg
      -description-02.jpg
      -description-03.jpg
      -description-04.jpg
      -
      -01-description.jpg
      -02-description.jpg
      -03-description.jpg
      -04-description.jpg
      +
      description-01.jpg
      +description-02.jpg
      +description-03.jpg
      +description-04.jpg
      +
      +01-description.jpg
      +02-description.jpg
      +03-description.jpg
      +04-description.jpg
      description-01.jpg
      +description-02.jpg
      +description-03.jpg
      +description-04.jpg
      +
      +01-description.jpg
      +02-description.jpg
      +03-description.jpg
      +04-description.jpg

      Keep dates or date ranges compact and start with year

      • Write dates without delimiters.
      • @@ -38783,13 +38783,13 @@ output = json

      • Use a double dash to separate two dates describing an interval: yyyy--yyyy. Start with the earliest date.

      Right:

      -
      description-20150401.php
      -description-201504.php
      -description-2015.php
      -description-2000--2010.php
      description-20150401.php
      -description-201504.php
      -description-2015.php
      -description-2000--2010.php
      +
      description-20150401.php
      +description-201504.php
      +description-2015.php
      +description-2000--2010.php
      description-20150401.php
      +description-201504.php
      +description-2015.php
      +description-2000--2010.php

      See 'ISO 8601' for further reading.

      Use special modifiers for target devices, image sizes or media queries, and pixel densities.

      Modifiers are inspired by Apple iOS naming conventions. There are some differences. Apple uses '@'as a delimiter for the section indicating higher resolution images, for example '@2x' for retina images. Because '@' is a reserved character and can create problems, we use Bourbon's convention: an underscore. Also, Apple uses a tilde (~) as a delimiter for a section indicating specific devices. Because also a tilde can create problems, we suggest to simply use a dash.

      @@ -38803,21 +38803,21 @@ output = json

    • When both the width and height should not exceed a dimension but the images should keep the original aspect ratio, add a 'max' (maximum) after the amount of pixels.

    Right:

    -
    description_2x.jpg
    -description-lap.jpg
    -description-desk.jpg
    -description-lap_2x.jpg
    -description-palm-1024w_2x.jpg
    -description-iphone5-568h_2x.jpg
    -description-palm-1024x768_2x.jpg
    -description-40max.jpg
    description_2x.jpg
    -description-lap.jpg
    -description-desk.jpg
    -description-lap_2x.jpg
    -description-palm-1024w_2x.jpg
    -description-iphone5-568h_2x.jpg
    -description-palm-1024x768_2x.jpg
    -description-40max.jpg
    +
    description_2x.jpg
    +description-lap.jpg
    +description-desk.jpg
    +description-lap_2x.jpg
    +description-palm-1024w_2x.jpg
    +description-iphone5-568h_2x.jpg
    +description-palm-1024x768_2x.jpg
    +description-40max.jpg
    description_2x.jpg
    +description-lap.jpg
    +description-desk.jpg
    +description-lap_2x.jpg
    +description-palm-1024w_2x.jpg
    +description-iphone5-568h_2x.jpg
    +description-palm-1024x768_2x.jpg
    +description-40max.jpg

    Use version numbers if available

    • Start version with a dash (-) as delimiter.
    • @@ -38826,18 +38826,18 @@ output = json

    • Types, such as 'a' (alpha), 'b' (beta), 'rc1' (release candidate 1) can be added without delimiters.

    Right:

    -
    description-0.5.js
    -description-1.0b.js
    -description-1.0rc1.js
    description-0.5.js
    -description-1.0b.js
    -description-1.0rc1.js
    +
    description-0.5.js
    +description-1.0b.js
    +description-1.0rc1.js
    description-0.5.js
    +description-1.0b.js
    +description-1.0rc1.js

    Add status when needed

    • You can optionally add a file status such as 'draft' and 'published'.
    • Start status with a dash.

    Right:

    -
    description-draft.md
    description-draft.md
    +
    description-draft.md
    description-draft.md

    Add language code only when different languages are available

    • Use a period to separate the language code from the rest of the file name.
    • @@ -38845,9 +38845,9 @@ output = json

    • Only add languages when different languages are available.

    Right:

    -
    description.nl.txt
    -description.en.txt
    description.nl.txt
    -description.en.txt
    +
    description.nl.txt
    +description.en.txt
    description.nl.txt
    +description.en.txt

    Add file conditions just before the file extension

    • The file condition should be the last part, just before the file extension.
    • @@ -38855,11 +38855,361 @@ output = json

    • Use periods (.) as a delimiter for different conditions.

    Right:

    -
    description.min.js
    -description.custom1234.min.js
    description.min.js
    -description.custom1234.min.js
    +
    description.min.js
    +description.custom1234.min.js
    description.min.js
    +description.custom1234.min.js

    Rewrite original file names not following conventions

    It is not preferred to keep file names in it's original format if it doesn't match your file name conventions. But in some cases it is easier to keep the file name untouched. Sometimes you want to easily replace a file with a newer one from the original source in the future.

    +]]> + + + <![CDATA[Proxies Configuration for Shells & Terminal]]> + https://note.toshiki.devdevelopment/proxy4shell-terminal + https://note.toshiki.devdevelopment/proxy4shell-terminal + Thu, 02 Nov 2023 00:00:00 GMT + Proxies Configuration for Shells & Terminal +

    TL;DR

    +

    This article discusses the configuration of proxies for shells and terminals. It explains the advantages of using proxy servers to bypass network restrictions and surveillance. The article provides examples of the challenges faced when accessing foreign services and shows how to set up a proxy tunnel using the curl command. It also provides scripts and instructions for setting up proxy switches in different shell environments, such as zsh, bash, and Windows CMD and PowerShell. The article concludes with additional information on proxy configurations for applications like ssh and tips for working with authentication procedures.

    +

    1. Background

    +

    Proxies or namely proxy servers are by far one of the most affordable or cost-effective option to establish a masked layer connection to bypass the network restrictions with the annoying surveillance tracked by a local network ISP as compared to a click-to-use VPN service, which generically requires more individual invest to protect themselves under the insecure internet environment nowadays. When a user resides within the environment where the local gateways of full, user-dominant open access towards the internet is censored or restricted with domestic network blockages by the country.

    +

    + +

    + while I adopt absolute subjective yet objective perspectives on the individual viewpoints towards the MIIT department of each country those of which applies the internet regulatory services within the national range for avoiding pitfalls on misleading information brought by cross-border influences; meanwhile regardlessly such measures are still facing controversial debates amongst publics that vastly limits the independent freedom rights, though advantages must not be underestimated, still. +

    2. The Major Issue

    +

    The majority of the issue still heavily preserves across the developmental fields which the layer of the blockage imposes limits on communicating with third-party, remote platforms such as Github or registries like NPM for frontend developments that stores key packages or components, as a requirement during a pre-built phase of a project. Most of the time foreign services becomes completely inaccessible or fortunately users could reach the services during a possible ISP maintenance downtime but normally the potentiality is mere, or hardly none yet the load speed before TTL connection expires are objectively slow, shortly before the origin site DNS being spoofed again. The unpleasant experiences with the networking somewhat affects interest on development reduces by high percentages or it even strand some awesome projects ran ashore ultimately.

    +

    The following screenshots are a more direct representation to visualize the differences between the connection towards one of the most beloved search engine, Google with the following command via curl.

    +
    sh
    curl -I google.com
    curl -I google.com
    +
    +

    The command is used to fetch the headers of a URL or web page. When you run "curl -I" followed by a URL, the command sends an HTTP HEAD request to the specified URL and retrieves the HTTP headers of the response. This allows you to view the information contained in the response headers without requesting and downloading the entire content of the page. The headers typically include details like the server information, content type, content length, status codes, and more.

    +
    +

    The following screenshot from terminal indicates the the final output of the package availability received without losses on a bare unmasked network environment, which returns FAIL in the final connection after a dry run fails 11s after when the TTL expires the connection fails.

    +

    +

    The next screenshot from terminal indicates a temporary proxy tunnel is established both in http and https protocol tunneled through a local proxy gateway at the local systemic IP address at 127.0.0.1 and exposes the proxy server at a mix of socks/https/http protocol port at 7890, just simply with the traditional export method by setting up in the nonce, the command is given as followed.

    +
    sh
    export http_proxy=http://127.0.0.1:7890
    +export https_proxy=$http_proxy
    export http_proxy=http://127.0.0.1:7890
    +export https_proxy=$http_proxy
    +

    And then we re-enter the same command with curl from above; surprisingly, the header responses returned TTP/1.1 200 OK, thus the conclusion drawn here is the proxy server we launched was successfully up and running with tunneled access towards foreign sites without restrictions! Hooray!

    +

    ◎ Curl in action with successful response header from Google

    +

    Since each proxy configuration might varies atop of the user preferred client, not including ShadowRocket, Clash, V2ray or other proprietary softwares that are licensed either behind a paywall to run with; or simply expensive to purchase a subscription; the proxy ports forwarded varies alongside the changes amongst clients. But the overall approach taken into the account still remains the same with the following traditional formats, the local IP of the machine (normally 127.0.0.1) followed after with the specified ports. In the scenario of the article is referenced as example, I chose Clash (in spite the entire Clash project repository as well as its affiliated forked projects are being taken down by anonymous reasons by either archiving the overall projects or simply shutting down due to possible legal actions or political reasons regarding the country of residency of various developers).

    +
    shj
    # http protocal
    +http://127.0.0.1:7890
    +# https protocal
    +https://127.0.0.1:7890
    # http protocal
    +http://127.0.0.1:7890
    +# https protocal
    +https://127.0.0.1:7890
    +

    2.1: Kill the Complexities; Unleash the Simplicity!

    +

    But, the logic routes to the central question on: How can we simplify the course of action on setting up proxies without manually run export command every single time we wish to use? Below is a simple approach by aliasing a shortcut code to a proxy switch script amended towards your shell configuration profile that initializes on every session startups, in this case I uses zsh since it's integrated as the default shell on macOS since the release of macOS Catalina, yet it's one of my most familiar and favored shell when was using other OS as well.

    +

    Though some people might use autosuggestion extensions as third-party shell features to automatically predict the command completion after a code piece is inputted such as zsh-autosuggestion plugin or fan of fish shell users has the native privilege of auto completions but I personally not fond of such featured integration since it might decelerate the load speed of an active session; I prefer stick tightly with original shell.

    +
    sh
    # open your shell profile with an preferred editor
    +$ vim ~/.zshrc
    +
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +
    +# restart your terminal with a new session or reload the config
    +$ source ~/.zshrc
    # open your shell profile with an preferred editor
    +$ vim ~/.zshrc
    +
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +
    +# restart your terminal with a new session or reload the config
    +$ source ~/.zshrc
    +

    The proxy essentially provides two shortcut command function defined with proxy_on and proxy_off. he proxy_on function sets the environment variables http_proxy and https_proxy to http://127.0.0.1:7890, which is the default proxy port of the traditional clash protocol, here is where you could replace the IP with other remote proxy servers or ports of other local proxies .Enabling a global proxy for the current terminal session. Meanwhile the proxy_off function unsets (removes) the http_proxy and https_proxy environment variables, effectively turning off the global proxy for the current terminal session. When any of the both executed, the indicator message will be echoed on the terminal, see the following screenshot in action.

    +

    ◎ Enabling the shell session proxy with script

    +

    After you reload your shell profile you can test out the scripted command yourself. To test whether the proxy has a successful setup after the proxy has been switched on, run echo $http_proxy or https_proxy with a dollar sign in front of the alias as an indicator for environmental variable, the third command as shown in the screenshot above, the command will simply print the configured variable value addressed to the specified alias. Contrarily, if your terminal returns the following resultant,

    +
    sh
    $ proxy_on
    +zsh: command not found: proxy_on
    $ proxy_on
    +zsh: command not found: proxy_on
    +

    Then you will have to distinguish the exact shell you are currently on, the hereinafter content are mainly targeted towards novice learners whom are unable to track the shell types or configuration on particular operating systems. The configuration file for each shell varies their file names as well the location of storage; while Mac users could directly apply changes based on the instruction provided above if your system if Catalina or above. To know what exactly the active shell running, run,

    +
    sh
    $ echo $SHELL
    $ echo $SHELL
    +

    The returned string text will be the name of the current active shell, the following is a list of the possible shell profile config name affiliated with each shell; most of the config profile files should be lied under the ~ or the root/home folder of each operating system with a dot in front of the file names are inferred as hidden file or directory in most of the Unix-like systems, such as macOS, Ubuntu, Debian and etc, but some of the config file such as fish shell could locate in an isolated config directory. The usual format of a config file is as followed,

    +
    shell
    ~/.zshrc
    ~/.zshrc
    +

    The following is a list of the most common shells with their possible profile file names that corresponded,

    +
      +
    • /bin/bash : .bash_profile or .bashrc
    • +
    • /bin/zsh : .zprofile or .zshrc
    • +
    • /bin/fish: ~/.config/fish/config
    • +
    +

    Still, the location might still varies, users might have to perform individual research to precisely locate their configuration file location, which is out of my jurisdiction of concerns (it's just evident action of procrastination and laziness, my apologies if none of the ones above fits your demand) ;).

    +

    + +

    +

    For Unix-like users, after you have specified your shell as well as your config file name and locations, copy the following code chunk as command and paste it back into your terminal and run to apply permanent changes to the configuration.

    +
    sh
    cat >> ~/.zshrc << EOF
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +EOF
    cat >> ~/.zshrc << EOF
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +EOF
    +

    The script above will write-in and install the proxy switch script and save the the content to the very end of the file. As a kindly reminder, if your shell is not zsh make sure to replace the string after cat >> to the actual path of your profile as well as your proxy server IP and port to the actual functioning details to your own demand; then ultimately, don't for get to reinitialize the shell by close and reopen the terminal or simply sourcing the config,

    +
    sh
    source ~/.zshrc
    source ~/.zshrc
    +

    To check whether the proxy script has taken its effect to the current session, don't forget to rerun the same echo command indicated as above. And up until here, the script has been properly installed and operatable as a charm, if your's still does not take any effect, go through the process again and read carefully through the documentation.

    +

    3: To All Windows Users

    +

    The documentation above are mainly targeted towards macOS & Linux users, to setup local proxy with Windows machines there is a complete different approach if you are more comfortably working with Powershells and CMD, since I disused windows less and less frequently by the time I decided to upgrade my device to macOS; even if I did use Windows my primary choice of developmental environment is still Linux by the native support of WSL with enhanced Ubuntu version in a virtual environment; the following commands are only done from my prior researches, I do not fully guarantee the usability of the commands, please use them at your own risks if any unexpected errors not only including system crashes or other affiliated damages, I do not relate responsibility to any of those presented.

    +

    +

    Simple concluding, abandon proprietary software, fall in the hug of open source; Linux even if most of the users might feel overwhelming when getting started with the system first :). Alright, enough with off-topic talkings, let's jump right in the process.

    +

    3.1: CMD

    +
    cmd
    set http_proxy=http://127.0.0.1:7890
    +set https_proxy=http://127.0.0.1:7890
    set http_proxy=http://127.0.0.1:7890
    +set https_proxy=http://127.0.0.1:7890
    +

    The commands are basically the same to Unix but the major difference is the amend commands in Windows are set instead of export. Once again I haven't personally tested the command, thus only use them as a reference. And whenever you wish to unset the global proxy for the session just simply run the set proxy command again but without any proxy server details.

    +
    cmd
    set http_proxy=
    +set https_proxy=
    set http_proxy=
    +set https_proxy=
    +

    3.2: PowerShell

    +

    Alike CMD, the string after are exactly the same but the setup prefix command differentiates,

    +
    powershell
    $env:http_proxy="http://127.0.0.1:1080"
    +$env:https_proxy="http://127.0.0.1:1080"
    $env:http_proxy="http://127.0.0.1:1080"
    +$env:https_proxy="http://127.0.0.1:1080"
    +

    And to revert to the default proxy setting, execute the following command to unset both the http and https proxy.

    +
    powershell
    $env:http_proxy=""
    +$env:https_proxy=""
    $env:http_proxy=""
    +$env:https_proxy=""
    +

    4: Extended Trivia on Proxy

    +

    Sometimes a proxy server may require an authentication procedure involving passcode for accessing before establishing a secure connection to interact with the server itself. From the partial article above we only discussed on a simple local proxy server setup including a host IP with its forwarded port gateways; but when facing the scenario described for a net connection, we will need a bit more complex method when working in the CLI environment.

    +

    Before we start, quoting from one of the answer from AskUbuntu, resolving the misconception on the difference between terminal application and the net utilities falls underly,

    +
    +

    Terminal is not net application. Maybe is better to say, in your case, terminal is container for net application like ssh, telnet, lftp, wget, lynx ...

    +
    +

    A terminal provides a command-line interface that allows users to send commands and receive responses from network applications, facilitating communication and control over a network connection. It acts as a mediator between the user and the network applications, enabling the user to send instructions and receive information, but not a proxy client.

    +

    + +

    +

    Done with the technical talkings, now let's dive into the actual configuration process of the shell. Other than simply inputting a host IP and a port followed, the following formats are the default configuration for a proxy server with HTTP connection protocol, follow the exact same process as described based on your shell type, modify the fields with the following,

    +
    shell
    export http_proxy=http://username:password@proxyhost:port/
    +export ftp_proxy=http://username:password@proxyhost:port/
    +export telnet_proxy=http://username:password@proxyhost:port/
    export http_proxy=http://username:password@proxyhost:port/
    +export ftp_proxy=http://username:password@proxyhost:port/
    +export telnet_proxy=http://username:password@proxyhost:port/
    +

    Another approach suggested by the same user whom provided the answer on AskUbuntu for all Ubuntu users, edit the proxy configuration at the root of your machine as follows,

    +
    sh
    sudo -H vim /etc/profile.d/proxy.sh
    sudo -H vim /etc/profile.d/proxy.sh
    +

    And add the exported proxy members aligning the format as above, then save and reinitialize the environment, viola. The patches edited are mainly targeted for incorporating with wget, ftp, lftp, telnet in terminal.

    +

    When working with ssh instance over a proxy, a different approach has to be taken since SSH library does not natively support SOCKS5 client, user will have to pass a ProxyCommand option as a workaround to apply proxied connection, below is an instance of socat,

    +
    sh
    ssh -o ProxyCommand='socat - SOCKS4A:myproxy:%h:%p,socksuser=nobody' user@host
    ssh -o ProxyCommand='socat - SOCKS4A:myproxy:%h:%p,socksuser=nobody' user@host
    +

    The proxyCommand option allows user to integrate socat as an intermediary mediator to establish connection above a proxy. Other alternatives like tsocks are as well viable to transparently use SOCKS for TCP traffic, Exemplifying running SOCKS5 over socat2,

    +
    bash
    ssh -o ProxyCommand='socat - "SOCKS5:%h:%p|tcp:myproxy:1080"' user@host
    ssh -o ProxyCommand='socat - "SOCKS5:%h:%p|tcp:myproxy:1080"' user@host
    +

    Further, socat2 for HTTP Proxy CONNECT method,

    +
    bash
    ssh -o ProxyCommand='socat - "PROXY:%h:%p|tcp:myproxy:80"' user@host
    ssh -o ProxyCommand='socat - "PROXY:%h:%p|tcp:myproxy:80"' user@host
    +
    +]]>
    + Proxies Configuration for Shells & Terminal +

    TL;DR

    +

    This article discusses the configuration of proxies for shells and terminals. It explains the advantages of using proxy servers to bypass network restrictions and surveillance. The article provides examples of the challenges faced when accessing foreign services and shows how to set up a proxy tunnel using the curl command. It also provides scripts and instructions for setting up proxy switches in different shell environments, such as zsh, bash, and Windows CMD and PowerShell. The article concludes with additional information on proxy configurations for applications like ssh and tips for working with authentication procedures.

    +

    1. Background

    +

    Proxies or namely proxy servers are by far one of the most affordable or cost-effective option to establish a masked layer connection to bypass the network restrictions with the annoying surveillance tracked by a local network ISP as compared to a click-to-use VPN service, which generically requires more individual invest to protect themselves under the insecure internet environment nowadays. When a user resides within the environment where the local gateways of full, user-dominant open access towards the internet is censored or restricted with domestic network blockages by the country.

    +

    + +

    + while I adopt absolute subjective yet objective perspectives on the individual viewpoints towards the MIIT department of each country those of which applies the internet regulatory services within the national range for avoiding pitfalls on misleading information brought by cross-border influences; meanwhile regardlessly such measures are still facing controversial debates amongst publics that vastly limits the independent freedom rights, though advantages must not be underestimated, still. +

    2. The Major Issue

    +

    The majority of the issue still heavily preserves across the developmental fields which the layer of the blockage imposes limits on communicating with third-party, remote platforms such as Github or registries like NPM for frontend developments that stores key packages or components, as a requirement during a pre-built phase of a project. Most of the time foreign services becomes completely inaccessible or fortunately users could reach the services during a possible ISP maintenance downtime but normally the potentiality is mere, or hardly none yet the load speed before TTL connection expires are objectively slow, shortly before the origin site DNS being spoofed again. The unpleasant experiences with the networking somewhat affects interest on development reduces by high percentages or it even strand some awesome projects ran ashore ultimately.

    +

    The following screenshots are a more direct representation to visualize the differences between the connection towards one of the most beloved search engine, Google with the following command via curl.

    +
    sh
    curl -I google.com
    curl -I google.com
    +
    +

    The command is used to fetch the headers of a URL or web page. When you run "curl -I" followed by a URL, the command sends an HTTP HEAD request to the specified URL and retrieves the HTTP headers of the response. This allows you to view the information contained in the response headers without requesting and downloading the entire content of the page. The headers typically include details like the server information, content type, content length, status codes, and more.

    +
    +

    The following screenshot from terminal indicates the the final output of the package availability received without losses on a bare unmasked network environment, which returns FAIL in the final connection after a dry run fails 11s after when the TTL expires the connection fails.

    +

    +

    The next screenshot from terminal indicates a temporary proxy tunnel is established both in http and https protocol tunneled through a local proxy gateway at the local systemic IP address at 127.0.0.1 and exposes the proxy server at a mix of socks/https/http protocol port at 7890, just simply with the traditional export method by setting up in the nonce, the command is given as followed.

    +
    sh
    export http_proxy=http://127.0.0.1:7890
    +export https_proxy=$http_proxy
    export http_proxy=http://127.0.0.1:7890
    +export https_proxy=$http_proxy
    +

    And then we re-enter the same command with curl from above; surprisingly, the header responses returned TTP/1.1 200 OK, thus the conclusion drawn here is the proxy server we launched was successfully up and running with tunneled access towards foreign sites without restrictions! Hooray!

    +

    ◎ Curl in action with successful response header from Google

    +

    Since each proxy configuration might varies atop of the user preferred client, not including ShadowRocket, Clash, V2ray or other proprietary softwares that are licensed either behind a paywall to run with; or simply expensive to purchase a subscription; the proxy ports forwarded varies alongside the changes amongst clients. But the overall approach taken into the account still remains the same with the following traditional formats, the local IP of the machine (normally 127.0.0.1) followed after with the specified ports. In the scenario of the article is referenced as example, I chose Clash (in spite the entire Clash project repository as well as its affiliated forked projects are being taken down by anonymous reasons by either archiving the overall projects or simply shutting down due to possible legal actions or political reasons regarding the country of residency of various developers).

    +
    shj
    # http protocal
    +http://127.0.0.1:7890
    +# https protocal
    +https://127.0.0.1:7890
    # http protocal
    +http://127.0.0.1:7890
    +# https protocal
    +https://127.0.0.1:7890
    +

    2.1: Kill the Complexities; Unleash the Simplicity!

    +

    But, the logic routes to the central question on: How can we simplify the course of action on setting up proxies without manually run export command every single time we wish to use? Below is a simple approach by aliasing a shortcut code to a proxy switch script amended towards your shell configuration profile that initializes on every session startups, in this case I uses zsh since it's integrated as the default shell on macOS since the release of macOS Catalina, yet it's one of my most familiar and favored shell when was using other OS as well.

    +

    Though some people might use autosuggestion extensions as third-party shell features to automatically predict the command completion after a code piece is inputted such as zsh-autosuggestion plugin or fan of fish shell users has the native privilege of auto completions but I personally not fond of such featured integration since it might decelerate the load speed of an active session; I prefer stick tightly with original shell.

    +
    sh
    # open your shell profile with an preferred editor
    +$ vim ~/.zshrc
    +
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +
    +# restart your terminal with a new session or reload the config
    +$ source ~/.zshrc
    # open your shell profile with an preferred editor
    +$ vim ~/.zshrc
    +
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +
    +# restart your terminal with a new session or reload the config
    +$ source ~/.zshrc
    +

    The proxy essentially provides two shortcut command function defined with proxy_on and proxy_off. he proxy_on function sets the environment variables http_proxy and https_proxy to http://127.0.0.1:7890, which is the default proxy port of the traditional clash protocol, here is where you could replace the IP with other remote proxy servers or ports of other local proxies .Enabling a global proxy for the current terminal session. Meanwhile the proxy_off function unsets (removes) the http_proxy and https_proxy environment variables, effectively turning off the global proxy for the current terminal session. When any of the both executed, the indicator message will be echoed on the terminal, see the following screenshot in action.

    +

    ◎ Enabling the shell session proxy with script

    +

    After you reload your shell profile you can test out the scripted command yourself. To test whether the proxy has a successful setup after the proxy has been switched on, run echo $http_proxy or https_proxy with a dollar sign in front of the alias as an indicator for environmental variable, the third command as shown in the screenshot above, the command will simply print the configured variable value addressed to the specified alias. Contrarily, if your terminal returns the following resultant,

    +
    sh
    $ proxy_on
    +zsh: command not found: proxy_on
    $ proxy_on
    +zsh: command not found: proxy_on
    +

    Then you will have to distinguish the exact shell you are currently on, the hereinafter content are mainly targeted towards novice learners whom are unable to track the shell types or configuration on particular operating systems. The configuration file for each shell varies their file names as well the location of storage; while Mac users could directly apply changes based on the instruction provided above if your system if Catalina or above. To know what exactly the active shell running, run,

    +
    sh
    $ echo $SHELL
    $ echo $SHELL
    +

    The returned string text will be the name of the current active shell, the following is a list of the possible shell profile config name affiliated with each shell; most of the config profile files should be lied under the ~ or the root/home folder of each operating system with a dot in front of the file names are inferred as hidden file or directory in most of the Unix-like systems, such as macOS, Ubuntu, Debian and etc, but some of the config file such as fish shell could locate in an isolated config directory. The usual format of a config file is as followed,

    +
    shell
    ~/.zshrc
    ~/.zshrc
    +

    The following is a list of the most common shells with their possible profile file names that corresponded,

    +
      +
    • /bin/bash : .bash_profile or .bashrc
    • +
    • /bin/zsh : .zprofile or .zshrc
    • +
    • /bin/fish: ~/.config/fish/config
    • +
    +

    Still, the location might still varies, users might have to perform individual research to precisely locate their configuration file location, which is out of my jurisdiction of concerns (it's just evident action of procrastination and laziness, my apologies if none of the ones above fits your demand) ;).

    +

    + +

    +

    For Unix-like users, after you have specified your shell as well as your config file name and locations, copy the following code chunk as command and paste it back into your terminal and run to apply permanent changes to the configuration.

    +
    sh
    cat >> ~/.zshrc << EOF
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +EOF
    cat >> ~/.zshrc << EOF
    +# session proxy switch shortcut
    +function proxy_on() {
    +    export http_proxy=http://127.0.0.1:7890
    +    export https_proxy=\$http_proxy
    +    echo -e "global proxy for the current terminal session has turned on"
    +}
    +
    +function proxy_off(){
    +    unset http_proxy https_proxy
    +    echo -e "global proxy for the current terminal session has turned off"
    +}
    +EOF
    +

    The script above will write-in and install the proxy switch script and save the the content to the very end of the file. As a kindly reminder, if your shell is not zsh make sure to replace the string after cat >> to the actual path of your profile as well as your proxy server IP and port to the actual functioning details to your own demand; then ultimately, don't for get to reinitialize the shell by close and reopen the terminal or simply sourcing the config,

    +
    sh
    source ~/.zshrc
    source ~/.zshrc
    +

    To check whether the proxy script has taken its effect to the current session, don't forget to rerun the same echo command indicated as above. And up until here, the script has been properly installed and operatable as a charm, if your's still does not take any effect, go through the process again and read carefully through the documentation.

    +

    3: To All Windows Users

    +

    The documentation above are mainly targeted towards macOS & Linux users, to setup local proxy with Windows machines there is a complete different approach if you are more comfortably working with Powershells and CMD, since I disused windows less and less frequently by the time I decided to upgrade my device to macOS; even if I did use Windows my primary choice of developmental environment is still Linux by the native support of WSL with enhanced Ubuntu version in a virtual environment; the following commands are only done from my prior researches, I do not fully guarantee the usability of the commands, please use them at your own risks if any unexpected errors not only including system crashes or other affiliated damages, I do not relate responsibility to any of those presented.

    +

    +

    Simple concluding, abandon proprietary software, fall in the hug of open source; Linux even if most of the users might feel overwhelming when getting started with the system first :). Alright, enough with off-topic talkings, let's jump right in the process.

    +

    3.1: CMD

    +
    cmd
    set http_proxy=http://127.0.0.1:7890
    +set https_proxy=http://127.0.0.1:7890
    set http_proxy=http://127.0.0.1:7890
    +set https_proxy=http://127.0.0.1:7890
    +

    The commands are basically the same to Unix but the major difference is the amend commands in Windows are set instead of export. Once again I haven't personally tested the command, thus only use them as a reference. And whenever you wish to unset the global proxy for the session just simply run the set proxy command again but without any proxy server details.

    +
    cmd
    set http_proxy=
    +set https_proxy=
    set http_proxy=
    +set https_proxy=
    +

    3.2: PowerShell

    +

    Alike CMD, the string after are exactly the same but the setup prefix command differentiates,

    +
    powershell
    $env:http_proxy="http://127.0.0.1:1080"
    +$env:https_proxy="http://127.0.0.1:1080"
    $env:http_proxy="http://127.0.0.1:1080"
    +$env:https_proxy="http://127.0.0.1:1080"
    +

    And to revert to the default proxy setting, execute the following command to unset both the http and https proxy.

    +
    powershell
    $env:http_proxy=""
    +$env:https_proxy=""
    $env:http_proxy=""
    +$env:https_proxy=""
    +

    4: Extended Trivia on Proxy

    +

    Sometimes a proxy server may require an authentication procedure involving passcode for accessing before establishing a secure connection to interact with the server itself. From the partial article above we only discussed on a simple local proxy server setup including a host IP with its forwarded port gateways; but when facing the scenario described for a net connection, we will need a bit more complex method when working in the CLI environment.

    +

    Before we start, quoting from one of the answer from AskUbuntu, resolving the misconception on the difference between terminal application and the net utilities falls underly,

    +
    +

    Terminal is not net application. Maybe is better to say, in your case, terminal is container for net application like ssh, telnet, lftp, wget, lynx ...

    +
    +

    A terminal provides a command-line interface that allows users to send commands and receive responses from network applications, facilitating communication and control over a network connection. It acts as a mediator between the user and the network applications, enabling the user to send instructions and receive information, but not a proxy client.

    +

    + +

    +

    Done with the technical talkings, now let's dive into the actual configuration process of the shell. Other than simply inputting a host IP and a port followed, the following formats are the default configuration for a proxy server with HTTP connection protocol, follow the exact same process as described based on your shell type, modify the fields with the following,

    +
    shell
    export http_proxy=http://username:password@proxyhost:port/
    +export ftp_proxy=http://username:password@proxyhost:port/
    +export telnet_proxy=http://username:password@proxyhost:port/
    export http_proxy=http://username:password@proxyhost:port/
    +export ftp_proxy=http://username:password@proxyhost:port/
    +export telnet_proxy=http://username:password@proxyhost:port/
    +

    Another approach suggested by the same user whom provided the answer on AskUbuntu for all Ubuntu users, edit the proxy configuration at the root of your machine as follows,

    +
    sh
    sudo -H vim /etc/profile.d/proxy.sh
    sudo -H vim /etc/profile.d/proxy.sh
    +

    And add the exported proxy members aligning the format as above, then save and reinitialize the environment, viola. The patches edited are mainly targeted for incorporating with wget, ftp, lftp, telnet in terminal.

    +

    When working with ssh instance over a proxy, a different approach has to be taken since SSH library does not natively support SOCKS5 client, user will have to pass a ProxyCommand option as a workaround to apply proxied connection, below is an instance of socat,

    +
    sh
    ssh -o ProxyCommand='socat - SOCKS4A:myproxy:%h:%p,socksuser=nobody' user@host
    ssh -o ProxyCommand='socat - SOCKS4A:myproxy:%h:%p,socksuser=nobody' user@host
    +

    The proxyCommand option allows user to integrate socat as an intermediary mediator to establish connection above a proxy. Other alternatives like tsocks are as well viable to transparently use SOCKS for TCP traffic, Exemplifying running SOCKS5 over socat2,

    +
    bash
    ssh -o ProxyCommand='socat - "SOCKS5:%h:%p|tcp:myproxy:1080"' user@host
    ssh -o ProxyCommand='socat - "SOCKS5:%h:%p|tcp:myproxy:1080"' user@host
    +

    Further, socat2 for HTTP Proxy CONNECT method,

    +
    bash
    ssh -o ProxyCommand='socat - "PROXY:%h:%p|tcp:myproxy:80"' user@host
    ssh -o ProxyCommand='socat - "PROXY:%h:%p|tcp:myproxy:80"' user@host
    +
    ]]>
    @@ -38872,70 +39222,70 @@ output = json

    You must generate an Access Key before getting started. All examples will utilize access_key_id and access_key_secret variables which represent the Access Key ID and Secret Access Key values you generated.

    With rclone installed, you may run rclone config to configure a new S3 storage provider. You will be prompted with a series of questions for the new prvider details.

    If you have already configured rclone in the past, you may run rclone config file to print the location of your rclone configuration file:

    -
    bash
    $ rclone config file
    -# Configuration file is stored at:
    -# ~/.config/rclone/rclone.conf
    $ rclone config file
    -# Configuration file is stored at:
    -# ~/.config/rclone/rclone.conf
    +
    bash
    $ rclone config file
    +# Configuration file is stored at:
    +# ~/.config/rclone/rclone.conf
    $ rclone config file
    +# Configuration file is stored at:
    +# ~/.config/rclone/rclone.conf

    Then use an editor (nano or vim, for example) to add or edit the new provider. This example assumes you are adding a new r2demo provider:

    -
    bash
    [r2]
    -type = s3
    -provider = Cloudflare
    -access_key_id = abc123 # Your access_key_id
    -secret_access_key = xyz456 # Your access_key_secret
    -endpoint = https://<accountid>.r2.cloudflarestorage.com
    -acl = private
    [r2]
    -type = s3
    -provider = Cloudflare
    -access_key_id = abc123 # Your access_key_id
    -secret_access_key = xyz456 # Your access_key_secret
    -endpoint = https://<accountid>.r2.cloudflarestorage.com
    -acl = private
    +
    bash
    [r2]
    +type = s3
    +provider = Cloudflare
    +access_key_id = abc123 # Your access_key_id
    +secret_access_key = xyz456 # Your access_key_secret
    +endpoint = https://<accountid>.r2.cloudflarestorage.com
    +acl = private
    [r2]
    +type = s3
    +provider = Cloudflare
    +access_key_id = abc123 # Your access_key_id
    +secret_access_key = xyz456 # Your access_key_secret
    +endpoint = https://<accountid>.r2.cloudflarestorage.com
    +acl = private

    You may then use the new rclone provider for any of your normal workflows.

    List buckets & objects

    The rclone tree command can be used to list the contents of the remote, in this case Cloudflare R2.

    -
    bash
    $ rclone tree r2demo:
    -# /
    -# ├── user-uploads
    -# │   └── foobar.png
    -# └── my-bucket-name
    -#     ├── cat.png
    -#     └── todos.txt
    +
    bash
    $ rclone tree r2demo:
    +# /
    +# ├── user-uploads
    +# │   └── foobar.png
    +# └── my-bucket-name
    +#     ├── cat.png
    +#     └── todos.txt
     
    -$ rclone tree r2demo:my-bucket-name
    -# /
    -# ├── cat.png
    -# └── todos.txt
    $ rclone tree r2demo:
    -# /
    -# ├── user-uploads
    -# │   └── foobar.png
    -# └── my-bucket-name
    -#     ├── cat.png
    -#     └── todos.txt
    +$ rclone tree r2demo:my-bucket-name
    +# /
    +# ├── cat.png
    +# └── todos.txt
    $ rclone tree r2demo:
    +# /
    +# ├── user-uploads
    +# │   └── foobar.png
    +# └── my-bucket-name
    +#     ├── cat.png
    +#     └── todos.txt
     
    -$ rclone tree r2demo:my-bucket-name
    -# /
    -# ├── cat.png
    -# └── todos.txt
    +$ rclone tree r2demo:my-bucket-name +# / +# ├── cat.png +# └── todos.txt

    Upload and retrieve objects

    The rclone copy command can be used to upload objects to an R2 bucket and vice versa - this allows you to upload files up to the 5 TB maximum object size that R2 supports.

    -
    bash
    # Upload dog.txt to the user-uploads bucket
    -$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    -$ rclone tree r2demo:user-uploads
    -# /
    -# ├── foobar.png
    -# └── dog.txt
    +
    bash
    # Upload dog.txt to the user-uploads bucket
    +$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    +$ rclone tree r2demo:user-uploads
    +# /
    +# ├── foobar.png
    +# └── dog.txt
     
    -# Download dog.txt from the user-uploads bucket
    -$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    # Upload dog.txt to the user-uploads bucket
    -$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    -$ rclone tree r2demo:user-uploads
    -# /
    -# ├── foobar.png
    -# └── dog.txt
    +# Download dog.txt from the user-uploads bucket
    +$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    # Upload dog.txt to the user-uploads bucket
    +$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    +$ rclone tree r2demo:user-uploads
    +# /
    +# ├── foobar.png
    +# └── dog.txt
     
    -# Download dog.txt from the user-uploads bucket
    -$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    +# Download dog.txt from the user-uploads bucket +$ rclone copy r2demo:user-uploads/dog.txt dog.txt

    Generate presigned URLs

    You can also generate presigned links which allow you to share public access to a file temporarily using the rclone link command.

    ]]> @@ -38944,70 +39294,70 @@ output = json

    You must generate an Access Key before getting started. All examples will utilize access_key_id and access_key_secret variables which represent the Access Key ID and Secret Access Key values you generated.

    With rclone installed, you may run rclone config to configure a new S3 storage provider. You will be prompted with a series of questions for the new prvider details.

    If you have already configured rclone in the past, you may run rclone config file to print the location of your rclone configuration file:

    -
    bash
    $ rclone config file
    -# Configuration file is stored at:
    -# ~/.config/rclone/rclone.conf
    $ rclone config file
    -# Configuration file is stored at:
    -# ~/.config/rclone/rclone.conf
    +
    bash
    $ rclone config file
    +# Configuration file is stored at:
    +# ~/.config/rclone/rclone.conf
    $ rclone config file
    +# Configuration file is stored at:
    +# ~/.config/rclone/rclone.conf

    Then use an editor (nano or vim, for example) to add or edit the new provider. This example assumes you are adding a new r2demo provider:

    -
    bash
    [r2]
    -type = s3
    -provider = Cloudflare
    -access_key_id = abc123 # Your access_key_id
    -secret_access_key = xyz456 # Your access_key_secret
    -endpoint = https://<accountid>.r2.cloudflarestorage.com
    -acl = private
    [r2]
    -type = s3
    -provider = Cloudflare
    -access_key_id = abc123 # Your access_key_id
    -secret_access_key = xyz456 # Your access_key_secret
    -endpoint = https://<accountid>.r2.cloudflarestorage.com
    -acl = private
    +
    bash
    [r2]
    +type = s3
    +provider = Cloudflare
    +access_key_id = abc123 # Your access_key_id
    +secret_access_key = xyz456 # Your access_key_secret
    +endpoint = https://<accountid>.r2.cloudflarestorage.com
    +acl = private
    [r2]
    +type = s3
    +provider = Cloudflare
    +access_key_id = abc123 # Your access_key_id
    +secret_access_key = xyz456 # Your access_key_secret
    +endpoint = https://<accountid>.r2.cloudflarestorage.com
    +acl = private

    You may then use the new rclone provider for any of your normal workflows.

    List buckets & objects

    The rclone tree command can be used to list the contents of the remote, in this case Cloudflare R2.

    -
    bash
    $ rclone tree r2demo:
    -# /
    -# ├── user-uploads
    -# │   └── foobar.png
    -# └── my-bucket-name
    -#     ├── cat.png
    -#     └── todos.txt
    +
    bash
    $ rclone tree r2demo:
    +# /
    +# ├── user-uploads
    +# │   └── foobar.png
    +# └── my-bucket-name
    +#     ├── cat.png
    +#     └── todos.txt
     
    -$ rclone tree r2demo:my-bucket-name
    -# /
    -# ├── cat.png
    -# └── todos.txt
    $ rclone tree r2demo:
    -# /
    -# ├── user-uploads
    -# │   └── foobar.png
    -# └── my-bucket-name
    -#     ├── cat.png
    -#     └── todos.txt
    +$ rclone tree r2demo:my-bucket-name
    +# /
    +# ├── cat.png
    +# └── todos.txt
    $ rclone tree r2demo:
    +# /
    +# ├── user-uploads
    +# │   └── foobar.png
    +# └── my-bucket-name
    +#     ├── cat.png
    +#     └── todos.txt
     
    -$ rclone tree r2demo:my-bucket-name
    -# /
    -# ├── cat.png
    -# └── todos.txt
    +$ rclone tree r2demo:my-bucket-name +# / +# ├── cat.png +# └── todos.txt

    Upload and retrieve objects

    The rclone copy command can be used to upload objects to an R2 bucket and vice versa - this allows you to upload files up to the 5 TB maximum object size that R2 supports.

    -
    bash
    # Upload dog.txt to the user-uploads bucket
    -$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    -$ rclone tree r2demo:user-uploads
    -# /
    -# ├── foobar.png
    -# └── dog.txt
    +
    bash
    # Upload dog.txt to the user-uploads bucket
    +$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    +$ rclone tree r2demo:user-uploads
    +# /
    +# ├── foobar.png
    +# └── dog.txt
     
    -# Download dog.txt from the user-uploads bucket
    -$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    # Upload dog.txt to the user-uploads bucket
    -$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    -$ rclone tree r2demo:user-uploads
    -# /
    -# ├── foobar.png
    -# └── dog.txt
    +# Download dog.txt from the user-uploads bucket
    +$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    # Upload dog.txt to the user-uploads bucket
    +$ rclone copy dog.txt r2demo:user-uploads/dog.txt
    +$ rclone tree r2demo:user-uploads
    +# /
    +# ├── foobar.png
    +# └── dog.txt
     
    -# Download dog.txt from the user-uploads bucket
    -$ rclone copy r2demo:user-uploads/dog.txt dog.txt
    +# Download dog.txt from the user-uploads bucket +$ rclone copy r2demo:user-uploads/dog.txt dog.txt

    Generate presigned URLs

    You can also generate presigned links which allow you to share public access to a file temporarily using the rclone link command.

    ]]> @@ -39019,15 +39369,15 @@ output = json

    Thu, 01 Jul 2021 00:00:00 GMT Git push results in "Authentication Failed”

    Issue

    -
    bash
    $ git push
    -Username for 'https://github.com': ${{ GITHUB_USERNAME }}
    -Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
    -remote: Invalid username or password.
    -fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
    $ git push
    -Username for 'https://github.com': ${{ GITHUB_USERNAME }}
    -Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
    -remote: Invalid username or password.
    -fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
    +
    bash
    $ git push
    +Username for 'https://github.com': ${{ GITHUB_USERNAME }}
    +Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
    +remote: Invalid username or password.
    +fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
    $ git push
    +Username for 'https://github.com': ${{ GITHUB_USERNAME }}
    +Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
    +remote: Invalid username or password.
    +fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'

    git push to GitHub remote branch failed via https protocol

    Solution

    Solution 1

    @@ -39035,9 +39385,9 @@ output = json

    If you enabled two-factor authentication in your GitHub account you won't be able to push via HTTPS using your accounts password. Instead you need to generate a personal access token. This can be done in the application settings of your GitHub account. Using this token as your password should allow you to push to your remote repository via HTTPS. Use your username as usual.

    You may also need to update the origin for your repository if it is set to HTTPS. Do this to switch to SSH:

    -
    bash
    $ git remote -v
    -$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
    $ git remote -v
    -$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
    +
    bash
    $ git remote -v
    +$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
    $ git remote -v
    +$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git

    Solution 2

    GitHub username & password/access token mismatched due to prior temporary Git config setup → Reset Git global username & email config or in current repository

    To set your global username/email configuration:

    @@ -39056,15 +39406,15 @@ output = json

    ]]> Git push results in "Authentication Failed”

    Issue

    -
    bash
    $ git push
    -Username for 'https://github.com': ${{ GITHUB_USERNAME }}
    -Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
    -remote: Invalid username or password.
    -fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
    $ git push
    -Username for 'https://github.com': ${{ GITHUB_USERNAME }}
    -Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
    -remote: Invalid username or password.
    -fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
    +
    bash
    $ git push
    +Username for 'https://github.com': ${{ GITHUB_USERNAME }}
    +Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
    +remote: Invalid username or password.
    +fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
    $ git push
    +Username for 'https://github.com': ${{ GITHUB_USERNAME }}
    +Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
    +remote: Invalid username or password.
    +fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'

    git push to GitHub remote branch failed via https protocol

    Solution

    Solution 1

    @@ -39072,9 +39422,9 @@ output = json

    If you enabled two-factor authentication in your GitHub account you won't be able to push via HTTPS using your accounts password. Instead you need to generate a personal access token. This can be done in the application settings of your GitHub account. Using this token as your password should allow you to push to your remote repository via HTTPS. Use your username as usual.

    You may also need to update the origin for your repository if it is set to HTTPS. Do this to switch to SSH:

    -
    bash
    $ git remote -v
    -$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
    $ git remote -v
    -$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
    +
    bash
    $ git remote -v
    +$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
    $ git remote -v
    +$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git

    Solution 2

    GitHub username & password/access token mismatched due to prior temporary Git config setup → Reset Git global username & email config or in current repository

    To set your global username/email configuration:

    @@ -39278,17 +39628,17 @@ const members = [ 1-1: Values

    1-1-1: Numbers

    Values of the number type are numeric values, normally written as follows,

    -
    js
    144
    144
    +
    js
    144
    144
    • Put this into a program, it will cause the number 144 to come into existence inside the computer, with the following bash script, 144 might looks like this in bits,

      -
      js
      0100000001100010000000000000000000000000000000000000000000000000
      0100000001100010000000000000000000000000000000000000000000000000
      +
      js
      0100000001100010000000000000000000000000000000000000000000000000
      0100000001100010000000000000000000000000000000000000000000000000
    • With the following bash script, 144 will be converted into binary values in integer form,

      -
      sh
      ip1=144 # defines a variable named ip1, with the value of 10
      -echo "obase=2;$ip1" | bc # convert the value to binary via bc
      ip1=144 # defines a variable named ip1, with the value of 10
      -echo "obase=2;$ip1" | bc # convert the value to binary via bc
      +
      sh
      ip1=144 # defines a variable named ip1, with the value of 10
      +echo "obase=2;$ip1" | bc # convert the value to binary via bc
      ip1=144 # defines a variable named ip1, with the value of 10
      +echo "obase=2;$ip1" | bc # convert the value to binary via bc
      • The variable ip1 is assigned the value 144.
      • The echo command prints out the string "obase=2;144", where "obase=2;" is an argument for bc that tells it to output the result in base 2 (binary), and "10" is the decimal number we want to convert.
      • @@ -39306,9 +39656,9 @@ const members = [
      • 52 bits, any whole number less than 2522^{52}, which is more than 101510^{15} will safely fit in a JavaScript number, numbers we are using stay well below that.

      Fractional numbers are written by using a dot,

      -
      js
      9.81
      9.81
      +
      js
      9.81
      9.81

      For extreme huge or tiny numbers, we can also use "scientific" notion by adding an e, followed by the exponent of the number,

      -
      js
      2.998e8
      2.998e8
      +
      js
      2.998e8
      2.998e8

      This indicates 2.998×108=299800002.998 \times 10^8 = 29980000.

      Calculations with whole numbers (referred as integers) that fits into 52 bits are guaranteed to be always precise, but calculation with fraction numbers are generally not.

        @@ -39323,7 +39673,7 @@ const members = [

        1-1-2: Arithmetic

        The main thing to do with numbers is arithmetic. Arithmetic operations such as addition or multiplication take two number values and produce a new number from them, the following is an example of calculation in JavaScript.

        -
        js
        100 + 4 * 11
        100 + 4 * 11
        +
        js
        100 + 4 * 11
        100 + 4 * 11
        • The + and * symbols are called operators.

          @@ -39336,7 +39686,7 @@ const members = [

        But we can still overwrite the steps of operation using a parenthesis around the addition,

        -
        js
        ;(100 + 4) * 11
        ;(100 + 4) * 11
        +
        js
        ;(100 + 4) * 11
        ;(100 + 4) * 11

        For subtraction, there is the - operator, and division can be done with /. When operators appear together without parentheses, they are applied is determined by the precedence of the operators.

        • When multiple operators with the same precedence appear next to each other (as 1-2+1), they are applied left to right (refers to PEMDAS).
        • @@ -39368,9 +39718,9 @@ const members = [
        • Strings are used to represent text.
        • Strings are usually written by enclosing the contents with quotes.
        -
        js
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        -'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        -'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        +
        js
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        +'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        +'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'

        TIP

        Both single and double quotes can be used to mark strings

          @@ -39383,17 +39733,17 @@ const members = [
        • New tab: Similarly like newlines, \t indicates a new tab being indented.

        Take the following string as an example,

        -
        js
        'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'
        'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'
        +
        js
        'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'
        'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'

        The following will be the rendered output,

        -
        js
        Lorem ipsum dolor sit amet,
        -consectetur adipiscing elit.
        Lorem ipsum dolor sit amet,
        -consectetur adipiscing elit.
        +
        js
        Lorem ipsum dolor sit amet,
        +consectetur adipiscing elit.
        Lorem ipsum dolor sit amet,
        +consectetur adipiscing elit.

        WARNING

        But the situations where we want a backslash in a string to just be a backslash instead of a special code. By using \\ would render the "just slash" to \ on output, instead of a special character, as follows,

        -
        js
        "A newline character is written like \"\\n\"."
        "A newline character is written like \"\\n\"."
        +
        js
        "A newline character is written like \"\\n\"."
        "A newline character is written like \"\\n\"."

        Strings cannot be divided, multiplied, or subtracted, unlike integers. But the + operator can be used on the. It concatenates (glues) the two strings together, the following example will produce the string "concatenate".

        -
        js
        'con' + 'cat' + 'e' + 'nate'
        'con' + 'cat' + 'e' + 'nate'
        +
        js
        'con' + 'cat' + 'e' + 'nate'
        'con' + 'cat' + 'e' + 'nate'
        1-1-3: Strings review
        • Nearly everything could be put into strings in JavaScript
        • @@ -39409,9 +39759,9 @@ const members = [

          1-1-3-FR: Further Reading

          From the example given in the prior section with a lot of backslashes, it might be hard to understand the concept on at what time the slash will be rendered and when it will be considered as a special character starter.

          The example is given as,

          -
          js
          "A newline character is written like \"\\n\"."
          "A newline character is written like \"\\n\"."
          +
          js
          "A newline character is written like \"\\n\"."
          "A newline character is written like \"\\n\"."

          The rendered output will be on print,

          -
          js
          A newline character is written like "\n".
          A newline character is written like "\n".
          +
          js
          A newline character is written like "\n".
          A newline character is written like "\n".

          the backslash character (\) is used as an escape character to indicate that the following character(s) should be treated specially. In this case, the "\n" sequence is an escape sequence that represents a newline character. The backslash before the n character tells the JavaScript interpreter that it should treat the n as a special character and not just as the letter "n".

          However, if we want to include an actual backslash character (\), we will have to escape it by using to two backslashes \\, or else with one single slash the JavaScript interpreter will still determines it as an special operator, Thus \\ will print \ on output.

            @@ -39421,7 +39771,7 @@ const members = [
          • In the given JavaScript string, the inner set of double quotation marks ("\\n") is escaped using a backslash (\) character. This tells the JavaScript interpreter to treat the inner double quotation marks as a regular character instead of a string delimiter.

            So when the string is rendered on output, the backslash character will be removed and the inner set of quotation marks will be displayed as a regular character. The rendered string will look like this,

            -
            js
            '\n'
            '\n'
            +
            js
            '\n'
            '\n'

            The outer set of double quotation marks in the original string delimit the entire string and will be displayed as regular quotation marks.

          @@ -39434,17 +39784,17 @@ const members = [ 1-1: Values

          1-1-1: Numbers

          Values of the number type are numeric values, normally written as follows,

          -
          js
          144
          144
          +
          js
          144
          144
          • Put this into a program, it will cause the number 144 to come into existence inside the computer, with the following bash script, 144 might looks like this in bits,

            -
            js
            0100000001100010000000000000000000000000000000000000000000000000
            0100000001100010000000000000000000000000000000000000000000000000
            +
            js
            0100000001100010000000000000000000000000000000000000000000000000
            0100000001100010000000000000000000000000000000000000000000000000
          • With the following bash script, 144 will be converted into binary values in integer form,

            -
            sh
            ip1=144 # defines a variable named ip1, with the value of 10
            -echo "obase=2;$ip1" | bc # convert the value to binary via bc
            ip1=144 # defines a variable named ip1, with the value of 10
            -echo "obase=2;$ip1" | bc # convert the value to binary via bc
            +
            sh
            ip1=144 # defines a variable named ip1, with the value of 10
            +echo "obase=2;$ip1" | bc # convert the value to binary via bc
            ip1=144 # defines a variable named ip1, with the value of 10
            +echo "obase=2;$ip1" | bc # convert the value to binary via bc
            • The variable ip1 is assigned the value 144.
            • The echo command prints out the string "obase=2;144", where "obase=2;" is an argument for bc that tells it to output the result in base 2 (binary), and "10" is the decimal number we want to convert.
            • @@ -39462,9 +39812,9 @@ const members = [
            • 52 bits, any whole number less than 2522^{52}, which is more than 101510^{15} will safely fit in a JavaScript number, numbers we are using stay well below that.

            Fractional numbers are written by using a dot,

            -
            js
            9.81
            9.81
            +
            js
            9.81
            9.81

            For extreme huge or tiny numbers, we can also use "scientific" notion by adding an e, followed by the exponent of the number,

            -
            js
            2.998e8
            2.998e8
            +
            js
            2.998e8
            2.998e8

            This indicates 2.998×108=299800002.998 \times 10^8 = 29980000.

            Calculations with whole numbers (referred as integers) that fits into 52 bits are guaranteed to be always precise, but calculation with fraction numbers are generally not.

              @@ -39479,7 +39829,7 @@ const members = [

        1-1-2: Arithmetic

        The main thing to do with numbers is arithmetic. Arithmetic operations such as addition or multiplication take two number values and produce a new number from them, the following is an example of calculation in JavaScript.

        -
        js
        100 + 4 * 11
        100 + 4 * 11
        +
        js
        100 + 4 * 11
        100 + 4 * 11
        • The + and * symbols are called operators.

          @@ -39492,7 +39842,7 @@ const members = [

        But we can still overwrite the steps of operation using a parenthesis around the addition,

        -
        js
        ;(100 + 4) * 11
        ;(100 + 4) * 11
        +
        js
        ;(100 + 4) * 11
        ;(100 + 4) * 11

        For subtraction, there is the - operator, and division can be done with /. When operators appear together without parentheses, they are applied is determined by the precedence of the operators.

        • When multiple operators with the same precedence appear next to each other (as 1-2+1), they are applied left to right (refers to PEMDAS).
        • @@ -39524,9 +39874,9 @@ const members = [
        • Strings are used to represent text.
        • Strings are usually written by enclosing the contents with quotes.
        -
        js
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        -'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        -'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        +
        js
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        +'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        +'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'

        TIP

        Both single and double quotes can be used to mark strings

          @@ -39539,17 +39889,17 @@ const members = [
        • New tab: Similarly like newlines, \t indicates a new tab being indented.

        Take the following string as an example,

        -
        js
        'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'
        'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'
        +
        js
        'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'
        'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'

        The following will be the rendered output,

        -
        js
        Lorem ipsum dolor sit amet,
        -consectetur adipiscing elit.
        Lorem ipsum dolor sit amet,
        -consectetur adipiscing elit.
        +
        js
        Lorem ipsum dolor sit amet,
        +consectetur adipiscing elit.
        Lorem ipsum dolor sit amet,
        +consectetur adipiscing elit.

        WARNING

        But the situations where we want a backslash in a string to just be a backslash instead of a special code. By using \\ would render the "just slash" to \ on output, instead of a special character, as follows,

        -
        js
        "A newline character is written like \"\\n\"."
        "A newline character is written like \"\\n\"."
        +
        js
        "A newline character is written like \"\\n\"."
        "A newline character is written like \"\\n\"."

        Strings cannot be divided, multiplied, or subtracted, unlike integers. But the + operator can be used on the. It concatenates (glues) the two strings together, the following example will produce the string "concatenate".

        -
        js
        'con' + 'cat' + 'e' + 'nate'
        'con' + 'cat' + 'e' + 'nate'
        +
        js
        'con' + 'cat' + 'e' + 'nate'
        'con' + 'cat' + 'e' + 'nate'
        1-1-3: Strings review
        • Nearly everything could be put into strings in JavaScript
        • @@ -39565,9 +39915,9 @@ const members = [

          1-1-3-FR: Further Reading

          From the example given in the prior section with a lot of backslashes, it might be hard to understand the concept on at what time the slash will be rendered and when it will be considered as a special character starter.

          The example is given as,

          -
          js
          "A newline character is written like \"\\n\"."
          "A newline character is written like \"\\n\"."
          +
          js
          "A newline character is written like \"\\n\"."
          "A newline character is written like \"\\n\"."

          The rendered output will be on print,

          -
          js
          A newline character is written like "\n".
          A newline character is written like "\n".
          +
          js
          A newline character is written like "\n".
          A newline character is written like "\n".

          the backslash character (\) is used as an escape character to indicate that the following character(s) should be treated specially. In this case, the "\n" sequence is an escape sequence that represents a newline character. The backslash before the n character tells the JavaScript interpreter that it should treat the n as a special character and not just as the letter "n".

          However, if we want to include an actual backslash character (\), we will have to escape it by using to two backslashes \\, or else with one single slash the JavaScript interpreter will still determines it as an special operator, Thus \\ will print \ on output.

            @@ -39577,7 +39927,7 @@ const members = [
          • In the given JavaScript string, the inner set of double quotation marks ("\\n") is escaped using a backslash (\) character. This tells the JavaScript interpreter to treat the inner double quotation marks as a regular character instead of a string delimiter.

            So when the string is rendered on output, the backslash character will be removed and the inner set of quotation marks will be displayed as a regular character. The rendered string will look like this,

            -
            js
            '\n'
            '\n'
            +
            js
            '\n'
            '\n'

            The outer set of double quotation marks in the original string delimit the entire string and will be displayed as regular quotation marks.

          diff --git a/getting-started.html b/getting-started.html index aaa37c03..d35a05b9 100644 --- a/getting-started.html +++ b/getting-started.html @@ -5,15 +5,15 @@ Git push results in "Authentication Failed” | Toshiki's Note - + - + - + - + @@ -36,18 +36,18 @@ -
          Skip to content

          Git push results in "Authentication Failed”

          Author:Anda Toshiki
          Updated:4 minutes ago
          Words:271
          Reading:1 min

          Issue

          bash
          $ git push
          -Username for 'https://github.com': ${{ GITHUB_USERNAME }}
          -Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
          -remote: Invalid username or password.
          -fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
          $ git push
          -Username for 'https://github.com': ${{ GITHUB_USERNAME }}
          -Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
          -remote: Invalid username or password.
          -fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'

          git push to GitHub remote branch failed via https protocol

          Solution

          Solution 1

          If you enabled two-factor authentication in your GitHub account you won't be able to push via HTTPS using your accounts password. Instead you need to generate a personal access token. This can be done in the application settings of your GitHub account. Using this token as your password should allow you to push to your remote repository via HTTPS. Use your username as usual.

          You may also need to update the origin for your repository if it is set to HTTPS. Do this to switch to SSH:

          bash
          $ git remote -v
          -$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
          $ git remote -v
          -$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git

          Solution 2

          GitHub username & password/access token mismatched due to prior temporary Git config setup → Reset Git global username & email config or in current repository

          To set your global username/email configuration:

          1. Open the command line.
          2. Set your username: git config --global user.name "FIRST_NAME LAST_NAME"
          3. Set your email address: git config --global user.email "MY_NAME@example.com"

          To set repository-specific username/email configuration:

          1. From the command line, change into the repository directory.
          2. Set your username: git config user.name "FIRST_NAME LAST_NAME"
          3. Set your email address: git config user.email "MY_NAME@example.com"
          4. Verify your configuration by displaying your configuration file: cat .git/config
          - +
          Skip to content

          Git push results in "Authentication Failed”

          Author:Anda Toshiki
          Updated:2 minutes ago
          Words:271
          Reading:1 min

          Issue

          bash
          $ git push
          +Username for 'https://github.com': ${{ GITHUB_USERNAME }}
          +Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
          +remote: Invalid username or password.
          +fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'
          $ git push
          +Username for 'https://github.com': ${{ GITHUB_USERNAME }}
          +Password for 'https://andatoshiki@github.com': ${{ GITHUB_PASSWORD }} # or GitHub personal access token
          +remote: Invalid username or password.
          +fatal: Authentication failed for 'https://github.com/andatoshiki/andatoshiki.git/'

          git push to GitHub remote branch failed via https protocol

          Solution

          Solution 1

          If you enabled two-factor authentication in your GitHub account you won't be able to push via HTTPS using your accounts password. Instead you need to generate a personal access token. This can be done in the application settings of your GitHub account. Using this token as your password should allow you to push to your remote repository via HTTPS. Use your username as usual.

          You may also need to update the origin for your repository if it is set to HTTPS. Do this to switch to SSH:

          bash
          $ git remote -v
          +$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git
          $ git remote -v
          +$ git remote set-url origin git@github.com:$USERNAME/$REPONAME.git

          Solution 2

          GitHub username & password/access token mismatched due to prior temporary Git config setup → Reset Git global username & email config or in current repository

          To set your global username/email configuration:

          1. Open the command line.
          2. Set your username: git config --global user.name "FIRST_NAME LAST_NAME"
          3. Set your email address: git config --global user.email "MY_NAME@example.com"

          To set repository-specific username/email configuration:

          1. From the command line, change into the repository directory.
          2. Set your username: git config user.name "FIRST_NAME LAST_NAME"
          3. Set your email address: git config user.email "MY_NAME@example.com"
          4. Verify your configuration by displaying your configuration file: cat .git/config
          + \ No newline at end of file diff --git a/hashmap.json b/hashmap.json index e74a10a1..d1f0b2e1 100644 --- a/hashmap.json +++ b/hashmap.json @@ -1 +1 @@ -{"academic_chemistry_problems_03-02-3.md":"5c40792d","academic_literature_index.md":"72bce40a","academic_chemistry_problems_03-02-2.md":"26afa053","academic_chemistry_problems_02-20.md":"7015a0e8","academic_literature_writing_methods-of-development.md":"b70ad7bf","academic_chemistry_notes_12-5.md":"4c698a37","academic_chemistry_problems_03-02-1.md":"054898d2","academic_physics_ipho-formulas-jpn_12.md":"b01af32f","academic_chemistry_index.md":"ca0457b9","academic_physics_ipho-formulas-jpn_1.md":"fa61cf48","application_vitepress-plugin-shiki-twoslash_api_queries.md":"9bd11a96","academic_physics_ipho-formulas-jpn_11.md":"5f6411f3","academic_physics_ipho-formulas-jpn_10.md":"5252ef94","academic_physics_ipho-formulas-jpn_6.md":"bc519d11","academic_physics_ipho-formulas-jpn_3.md":"aadd6536","academic_physics_index.md":"62b4f030","academic_physics_ipho-formulas-jpn_13.md":"5d106b26","academic_physics_ipho-formulas-jpn_2.md":"f9a6af54","academic_physics_ipho-formulas-jpn_4.md":"67c0b4f9","academic_physics_ipho-formulas-jpn_7.md":"353d535e","development_aws_handson-qabot.md":"3c125433","academic_physics_ipho-formulas-jpn_8.md":"f1df91b7","academic_physics_ipho-formulas-jpn_9.md":"da4d857a","academic_vocabulary_2023_02_2023-02-27.md":"06541670","academic_vocabulary_index.md":"f4afb44a","application_markdown-it-katex_how-to-use.md":"e6ab0018","application_markdown-it-katex_tips.md":"4fa4c33c","application_vitepress-plugin-shiki-twoslash_api_annotations.md":"105e6b7f","application_vitepress-plugin-shiki-twoslash_api_cutting.md":"b6b7a28c","application_vitepress-plugin-shiki-twoslash_api_emit.md":"8d757f81","application_vitepress-plugin-shiki-twoslash_api_errors.md":"8032d46f","application_vitepress-plugin-shiki-twoslash_api_includes.md":"d69b2a67","application_vitepress-plugin-shiki-twoslash_api_logging.md":"d3641bab","application_vitepress-plugin-shiki-twoslash_api_multi-file.md":"aea0802f","application_vitepress-plugin-shiki-twoslash_config_flags.md":"a683705b","application_vitepress-plugin-shiki-twoslash_config_reference.md":"42f9e642","application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md":"58ed95fc","application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md":"6731e737","application_vitepress-plugin-shiki-twoslash_index.md":"7fc07d32","development_aws_acknowledgement.md":"daba60ba","development_aws_appendix.md":"568c3e80","development_aws_author.md":"025b6bde","development_aws_aws-get-started.md":"e1a56953","development_aws_closing.md":"cf9dad64","development_aws_cloud.md":"e679b136","development_aws_docker-system.md":"4275fd21","development_aws_handson-bashoutter.md":"d59bc53b","development_aws_handson-ec2.md":"2a763e5b","development_aws_handson-jupyter.md":"7f479319","development_aws_index.md":"1f9e71a6","development_aws_license.md":"5f519b50","academic_physics_ipho-formulas-jpn_5.md":"6c32aa10","development_aws_assignments.md":"35fe9703","application_vitepress-plugin-shiki-twoslash_api_types.md":"9dbcbe1c","development_aws_aws-batch.md":"de2d649a","development_aws_main.md":"58c079df","development_aws_scientific-computing.md":"1b192c5b","development_aws_serverless.md":"715b8a8d","development_aws_webserver.md":"441ce29f","development_file-naming-convention.md":"ff928233","development_rclone-for-r2.md":"72ca2dcc","getting-started.md":"54a05997","index.md":"bcdaa8d8","javascript_notes_1_1-1.md":"444635ea","javascript_notes_1_1-2.md":"cddd09d6","jp_index.md":"5b353799","roadmap.md":"d668d571","save_reading_index.md":"d900b2c8","save_reading_outliers_1.md":"64c11331","save_reading_outliers_2.md":"74187620","save_reading_outliers_3.md":"0cab1bb8","save_reading_outliers_4.md":"d65868f7","development_aws_handson-serverless.md":"330af1e8","application_markdown-it-katex_support-function.md":"009fe258","application_markdown-it-katex_support-table.md":"52b042b8"} +{"application_vitepress-plugin-shiki-twoslash_api_emit.md":"07068d46","application_vitepress-plugin-shiki-twoslash_api_errors.md":"230e0002","application_vitepress-plugin-shiki-twoslash_api_annotations.md":"a42ad2a7","academic_chemistry_index.md":"56f381d7","application_vitepress-plugin-shiki-twoslash_api_logging.md":"8b741477","application_vitepress-plugin-shiki-twoslash_api_includes.md":"b534e723","academic_physics_ipho-formulas-jpn_3.md":"6485844d","application_vitepress-plugin-shiki-twoslash_api_multi-file.md":"48f61f4c","application_vitepress-plugin-shiki-twoslash_api_cutting.md":"2a5fd9c3","academic_chemistry_problems_03-02-2.md":"a4b8c746","academic_physics_ipho-formulas-jpn_6.md":"d563d3f1","academic_physics_ipho-formulas-jpn_7.md":"b0bd68dd","academic_chemistry_problems_02-20.md":"86be96e0","development_aws_handson-jupyter.md":"e87bcd1f","development_aws_handson-qabot.md":"27ff1082","academic_physics_ipho-formulas-jpn_8.md":"f05c02fb","academic_chemistry_notes_12-5.md":"f9fc6ef4","academic_physics_ipho-formulas-jpn_9.md":"083302ab","academic_vocabulary_2023_02_2023-02-27.md":"3ec19aaf","academic_vocabulary_index.md":"37eb0530","application_markdown-it-katex_how-to-use.md":"b10dd06e","application_vitepress-plugin-shiki-twoslash_api_queries.md":"8c3dbc97","academic_chemistry_problems_03-02-3.md":"152b3eb2","academic_literature_writing_methods-of-development.md":"bcfb091e","academic_physics_ipho-formulas-jpn_5.md":"948cb5df","academic_physics_index.md":"6ec0ff5a","academic_physics_ipho-formulas-jpn_10.md":"2eaa8ad2","academic_physics_ipho-formulas-jpn_11.md":"3b777f56","academic_physics_ipho-formulas-jpn_1.md":"b1c8984c","academic_physics_ipho-formulas-jpn_12.md":"449de813","academic_physics_ipho-formulas-jpn_13.md":"20d2560f","academic_physics_ipho-formulas-jpn_2.md":"6d273404","application_vitepress-plugin-shiki-twoslash_api_types.md":"a1a99084","academic_chemistry_problems_03-02-1.md":"a9ee56be","application_vitepress-plugin-shiki-twoslash_config_flags.md":"52b87b95","application_vitepress-plugin-shiki-twoslash_config_reference.md":"e7b86a5d","application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md":"287ab776","application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md":"a9cd6c63","development_aws_acknowledgement.md":"ebd64504","application_vitepress-plugin-shiki-twoslash_index.md":"e8d8a5ec","development_aws_appendix.md":"071021e4","development_aws_assignments.md":"fcb27d2d","development_aws_author.md":"a292956b","development_aws_closing.md":"0cdd4f54","development_aws_cloud.md":"148d68f2","development_aws_aws-batch.md":"76d54c51","development_aws_aws-get-started.md":"5e1dfdb2","development_aws_docker-system.md":"dcee24fc","development_aws_handson-bashoutter.md":"890a8ec8","development_aws_handson-ec2.md":"43188290","development_aws_index.md":"0fcf5beb","development_aws_scientific-computing.md":"194874e2","development_aws_serverless.md":"a89d6134","development_aws_webserver.md":"89157904","development_aws_handson-serverless.md":"7fbfa1f9","development_file-naming-convention.md":"0fb858f4","development_proxy4shell-terminal.md":"a93dc7e4","development_rclone-for-r2.md":"65c0da34","development_aws_license.md":"38e84b81","getting-started.md":"975024a7","index.md":"b89ea33b","academic_physics_ipho-formulas-jpn_4.md":"47f0821f","javascript_notes_1_1-1.md":"442433d3","jp_index.md":"f593c74c","javascript_notes_1_1-2.md":"cf1c6a03","roadmap.md":"233c3dec","save_reading_outliers_3.md":"ea35e051","save_reading_outliers_4.md":"8f24b5aa","development_aws_main.md":"587d14dd","save_reading_outliers_1.md":"9f6d6e06","save_reading_outliers_2.md":"0f26746f","save_reading_index.md":"684b6d50","application_markdown-it-katex_tips.md":"d87fb855","academic_literature_index.md":"bd51fa1c","application_markdown-it-katex_support-function.md":"59634b4a","application_markdown-it-katex_support-table.md":"419e3a5e"} diff --git a/index.html b/index.html index 4353bdab..2492b66f 100644 --- a/index.html +++ b/index.html @@ -5,14 +5,14 @@ Toshiki's Notebook | Eternal digital knowledge base for content creation and notes management. - + - + - + - + @@ -35,8 +35,8 @@ -
          Skip to content

          Toshiki's Notebook

          Research & Produce

          👨‍💻 Eternal & digital knowledge base for content creation and notes management.

          Home logo
          - +
          Skip to content

          Toshiki's Notebook

          Research & Produce

          👨‍💻 Eternal & digital knowledge base for content creation and notes management.

          Home logo
          + \ No newline at end of file diff --git a/javascript/notes/1/1-1.html b/javascript/notes/1/1-1.html index 451620d2..daa969c0 100644 --- a/javascript/notes/1/1-1.html +++ b/javascript/notes/1/1-1.html @@ -5,15 +5,15 @@ 1-1: Values | Toshiki's Note - + - + - + - + @@ -36,14 +36,14 @@ -
          Skip to content

          1-1: Values

          Author:Anda Toshiki
          Updated:4 minutes ago
          Words:1.5k
          Reading:9 min

          1-1-1: Numbers

          Values of the number type are numeric values, normally written as follows,

          js
          144
          144
          • Put this into a program, it will cause the number 144 to come into existence inside the computer, with the following bash script, 144 might looks like this in bits,

            js
            0100000001100010000000000000000000000000000000000000000000000000
            0100000001100010000000000000000000000000000000000000000000000000
          • With the following bash script, 144 will be converted into binary values in integer form,

            sh
            ip1=144 # defines a variable named ip1, with the value of 10
            -echo "obase=2;$ip1" | bc # convert the value to binary via bc
            ip1=144 # defines a variable named ip1, with the value of 10
            -echo "obase=2;$ip1" | bc # convert the value to binary via bc
            • The variable ip1 is assigned the value 144.
            • The echo command prints out the string "obase=2;144", where "obase=2;" is an argument for bc that tells it to output the result in base 2 (binary), and "10" is the decimal number we want to convert.
            • The output of the echo command is piped (using the | character) to bc, which takes the input "obase=2;144" and interprets it as a command to convert the number 10 to binary.
            • Finally, the binary equivalent of 144, which is "10010000", is printed to the terminal.

          TIP

          But the standard describes JavaScript numbers as 64-bit floating-point values, which indicates fractions and exponents are available.

          Not all whole numbers 101910^{19} fit in a JavaScript number. There are also negative numbers, so one of the bits has to be used to store the sign of the number.

          • 11 bits are used to store the position of the decimal dot within the number.
          • 52 bits, any whole number less than 2522^{52}, which is more than 101510^{15} will safely fit in a JavaScript number, numbers we are using stay well below that.

          Fractional numbers are written by using a dot,

          js
          9.81
          9.81

          For extreme huge or tiny numbers, we can also use "scientific" notion by adding an e, followed by the exponent of the number,

          js
          2.998e8
          2.998e8

          This indicates 2.998×108=299800002.998 \times 10^8 = 29980000.

          Calculations with whole numbers (referred as integers) that fits into 52 bits are guaranteed to be always precise, but calculation with fraction numbers are generally not.

          • Such as π\pi cannot be precisely expressed by a finite amount of decimal digits, thus many numbers lose some precision when only 64 bits are available to store them.
          1-1-1: Numbers review
          • 64 bits: A 64-bit number is a binary sequence of 64 bits, which can represent 2642^{64} (18,446,744,073,709,551,616) different values. This is commonly used for representing memory addresses and integers with large values in computer systems.
          • 11 bits: An 11-bit number is a binary sequence of 11 bits, which can represent 2112^{11} (2,048) different values. This is often used in computer systems for encoding small integers, such as color values in images.
          • 52 bits: A 52-bit number is a binary sequence of 52 bits, which can represent 2522^{52} (4,503,599,627,370,496) different values. This is often used for representing the significand or mantissa portion of a floating-point number in computer systems.

          1-1-2: Arithmetic

          The main thing to do with numbers is arithmetic. Arithmetic operations such as addition or multiplication take two number values and produce a new number from them, the following is an example of calculation in JavaScript.

          js
          100 + 4 * 11
          100 + 4 * 11
          • The + and * symbols are called operators.

            • + apparently stands for addition while * stands for multiplication.
          • This expression indicates the multiplication takes place first then the adding of 100 comes next as a regard to PEMDAS rules (Order of Operations).

          But we can still overwrite the steps of operation using a parenthesis around the addition,

          js
          ;(100 + 4) * 11
          ;(100 + 4) * 11

          For subtraction, there is the - operator, and division can be done with /. When operators appear together without parentheses, they are applied is determined by the precedence of the operators.

          • When multiple operators with the same precedence appear next to each other (as 1-2+1), they are applied left to right (refers to PEMDAS).
          • Precedence: Priorities.

          WARNING

          When is doubt, don't care about precedence, just add parentheses for order of operation.

          There is one more arithmetic operator, which is the % percent sign used to represent the modulo operation. The term "X modulo Y" is defined as the remainder of dividing X by Y.

          • For example, 314 % 100 is 14, 10 % 3 is 1, and 144 % 12 is 0 because there are no remainders.
          • Modulo's precedence is the same as that of multiplication and division.
          1-2: Arithmetic review
          • All of the operators in JavaScript follows precedence rules, or referred as PEMDAS in conventional math.
            • + and - has the same lowest precedence.
            • * , / and % has the same medium precedence.
            • () has the highest precedence, followed on with brackets.
          • The symbol % refers to "modulo", in mathematical reading, we say "X modulo Y" is the remainder of X over Y.

          1-1-3: Strings

          The next data type is the string. Its use is not as evident from its name as with numbers, it also fulfills a very basic role.

          • Strings are used to represent text.
          • Strings are usually written by enclosing the contents with quotes.
          js
          'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
          -'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
          'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
          -'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'

          TIP

          Both single and double quotes can be used to mark strings

          • As long as the quotes at the start and the end of the string match.

          Almost anything can be put between quotes, and JavaScript will make a string value out of it. But the followings are tricky to be put between quotes.

          • Newlines: The things we get when we press enter on keyboard. We uses \n to represent.
          • New tab: Similarly like newlines, \t indicates a new tab being indented.

          Take the following string as an example,

          js
          'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'
          'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'

          The following will be the rendered output,

          js
          Lorem ipsum dolor sit amet,
          -consectetur adipiscing elit.
          Lorem ipsum dolor sit amet,
          -consectetur adipiscing elit.

          WARNING

          But the situations where we want a backslash in a string to just be a backslash instead of a special code. By using \\ would render the "just slash" to \ on output, instead of a special character, as follows,

          js
          "A newline character is written like \"\\n\"."
          "A newline character is written like \"\\n\"."

          Strings cannot be divided, multiplied, or subtracted, unlike integers. But the + operator can be used on the. It concatenates (glues) the two strings together, the following example will produce the string "concatenate".

          js
          'con' + 'cat' + 'e' + 'nate'
          'con' + 'cat' + 'e' + 'nate'
          1-1-3: Strings review
          • Nearly everything could be put into strings in JavaScript
          • String could be wrapped with "" double quotation marks or '' single quotation marks.
          • There is a tricky situation in JavaScript's string, where \ backslash followed with a character are being introduced specially by the interpreter, such as \n referred as newline, \t referred as new tab.
            • \\ double backslash will be rendered as a single \.
            • \& symbols followed after slash will not contain its original function such as connecting, but will be rendered as & on output.

          1-1-3-FR: Further Reading

          From the example given in the prior section with a lot of backslashes, it might be hard to understand the concept on at what time the slash will be rendered and when it will be considered as a special character starter.

          The example is given as,

          js
          "A newline character is written like \"\\n\"."
          "A newline character is written like \"\\n\"."

          The rendered output will be on print,

          js
          A newline character is written like "\n".
          A newline character is written like "\n".

          the backslash character (\) is used as an escape character to indicate that the following character(s) should be treated specially. In this case, the "\n" sequence is an escape sequence that represents a newline character. The backslash before the n character tells the JavaScript interpreter that it should treat the n as a special character and not just as the letter "n".

          However, if we want to include an actual backslash character (\), we will have to escape it by using to two backslashes \\, or else with one single slash the JavaScript interpreter will still determines it as an special operator, Thus \\ will print \ on output.

          • But what about the quotation marks used within the quotation marks that wraps the string? Wouldn't JavaScript interpreter throw error?

            • In the given JavaScript string, the inner set of double quotation marks ("\\n") is escaped using a backslash (\) character. This tells the JavaScript interpreter to treat the inner double quotation marks as a regular character instead of a string delimiter.

              So when the string is rendered on output, the backslash character will be removed and the inner set of quotation marks will be displayed as a regular character. The rendered string will look like this,

              js
              '\n'
              '\n'

              The outer set of double quotation marks in the original string delimit the entire string and will be displayed as regular quotation marks.

          Source: ChatGPT CA (Code Analysis)

          - +
          Skip to content

          1-1: Values

          Author:Anda Toshiki
          Updated:2 minutes ago
          Words:1.5k
          Reading:9 min

          1-1-1: Numbers

          Values of the number type are numeric values, normally written as follows,

          js
          144
          144
          • Put this into a program, it will cause the number 144 to come into existence inside the computer, with the following bash script, 144 might looks like this in bits,

            js
            0100000001100010000000000000000000000000000000000000000000000000
            0100000001100010000000000000000000000000000000000000000000000000
          • With the following bash script, 144 will be converted into binary values in integer form,

            sh
            ip1=144 # defines a variable named ip1, with the value of 10
            +echo "obase=2;$ip1" | bc # convert the value to binary via bc
            ip1=144 # defines a variable named ip1, with the value of 10
            +echo "obase=2;$ip1" | bc # convert the value to binary via bc
            • The variable ip1 is assigned the value 144.
            • The echo command prints out the string "obase=2;144", where "obase=2;" is an argument for bc that tells it to output the result in base 2 (binary), and "10" is the decimal number we want to convert.
            • The output of the echo command is piped (using the | character) to bc, which takes the input "obase=2;144" and interprets it as a command to convert the number 10 to binary.
            • Finally, the binary equivalent of 144, which is "10010000", is printed to the terminal.

          TIP

          But the standard describes JavaScript numbers as 64-bit floating-point values, which indicates fractions and exponents are available.

          Not all whole numbers 101910^{19} fit in a JavaScript number. There are also negative numbers, so one of the bits has to be used to store the sign of the number.

          • 11 bits are used to store the position of the decimal dot within the number.
          • 52 bits, any whole number less than 2522^{52}, which is more than 101510^{15} will safely fit in a JavaScript number, numbers we are using stay well below that.

          Fractional numbers are written by using a dot,

          js
          9.81
          9.81

          For extreme huge or tiny numbers, we can also use "scientific" notion by adding an e, followed by the exponent of the number,

          js
          2.998e8
          2.998e8

          This indicates 2.998×108=299800002.998 \times 10^8 = 29980000.

          Calculations with whole numbers (referred as integers) that fits into 52 bits are guaranteed to be always precise, but calculation with fraction numbers are generally not.

          • Such as π\pi cannot be precisely expressed by a finite amount of decimal digits, thus many numbers lose some precision when only 64 bits are available to store them.
          1-1-1: Numbers review
          • 64 bits: A 64-bit number is a binary sequence of 64 bits, which can represent 2642^{64} (18,446,744,073,709,551,616) different values. This is commonly used for representing memory addresses and integers with large values in computer systems.
          • 11 bits: An 11-bit number is a binary sequence of 11 bits, which can represent 2112^{11} (2,048) different values. This is often used in computer systems for encoding small integers, such as color values in images.
          • 52 bits: A 52-bit number is a binary sequence of 52 bits, which can represent 2522^{52} (4,503,599,627,370,496) different values. This is often used for representing the significand or mantissa portion of a floating-point number in computer systems.

          1-1-2: Arithmetic

          The main thing to do with numbers is arithmetic. Arithmetic operations such as addition or multiplication take two number values and produce a new number from them, the following is an example of calculation in JavaScript.

          js
          100 + 4 * 11
          100 + 4 * 11
          • The + and * symbols are called operators.

            • + apparently stands for addition while * stands for multiplication.
          • This expression indicates the multiplication takes place first then the adding of 100 comes next as a regard to PEMDAS rules (Order of Operations).

          But we can still overwrite the steps of operation using a parenthesis around the addition,

          js
          ;(100 + 4) * 11
          ;(100 + 4) * 11

          For subtraction, there is the - operator, and division can be done with /. When operators appear together without parentheses, they are applied is determined by the precedence of the operators.

          • When multiple operators with the same precedence appear next to each other (as 1-2+1), they are applied left to right (refers to PEMDAS).
          • Precedence: Priorities.

          WARNING

          When is doubt, don't care about precedence, just add parentheses for order of operation.

          There is one more arithmetic operator, which is the % percent sign used to represent the modulo operation. The term "X modulo Y" is defined as the remainder of dividing X by Y.

          • For example, 314 % 100 is 14, 10 % 3 is 1, and 144 % 12 is 0 because there are no remainders.
          • Modulo's precedence is the same as that of multiplication and division.
          1-2: Arithmetic review
          • All of the operators in JavaScript follows precedence rules, or referred as PEMDAS in conventional math.
            • + and - has the same lowest precedence.
            • * , / and % has the same medium precedence.
            • () has the highest precedence, followed on with brackets.
          • The symbol % refers to "modulo", in mathematical reading, we say "X modulo Y" is the remainder of X over Y.

          1-1-3: Strings

          The next data type is the string. Its use is not as evident from its name as with numbers, it also fulfills a very basic role.

          • Strings are used to represent text.
          • Strings are usually written by enclosing the contents with quotes.
          js
          'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
          +'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
          'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
          +'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'

          TIP

          Both single and double quotes can be used to mark strings

          • As long as the quotes at the start and the end of the string match.

          Almost anything can be put between quotes, and JavaScript will make a string value out of it. But the followings are tricky to be put between quotes.

          • Newlines: The things we get when we press enter on keyboard. We uses \n to represent.
          • New tab: Similarly like newlines, \t indicates a new tab being indented.

          Take the following string as an example,

          js
          'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'
          'Lorem ipsum dolor sit amet,\n consectetur adipiscing elit.'

          The following will be the rendered output,

          js
          Lorem ipsum dolor sit amet,
          +consectetur adipiscing elit.
          Lorem ipsum dolor sit amet,
          +consectetur adipiscing elit.

          WARNING

          But the situations where we want a backslash in a string to just be a backslash instead of a special code. By using \\ would render the "just slash" to \ on output, instead of a special character, as follows,

          js
          "A newline character is written like \"\\n\"."
          "A newline character is written like \"\\n\"."

          Strings cannot be divided, multiplied, or subtracted, unlike integers. But the + operator can be used on the. It concatenates (glues) the two strings together, the following example will produce the string "concatenate".

          js
          'con' + 'cat' + 'e' + 'nate'
          'con' + 'cat' + 'e' + 'nate'
          1-1-3: Strings review
          • Nearly everything could be put into strings in JavaScript
          • String could be wrapped with "" double quotation marks or '' single quotation marks.
          • There is a tricky situation in JavaScript's string, where \ backslash followed with a character are being introduced specially by the interpreter, such as \n referred as newline, \t referred as new tab.
            • \\ double backslash will be rendered as a single \.
            • \& symbols followed after slash will not contain its original function such as connecting, but will be rendered as & on output.

          1-1-3-FR: Further Reading

          From the example given in the prior section with a lot of backslashes, it might be hard to understand the concept on at what time the slash will be rendered and when it will be considered as a special character starter.

          The example is given as,

          js
          "A newline character is written like \"\\n\"."
          "A newline character is written like \"\\n\"."

          The rendered output will be on print,

          js
          A newline character is written like "\n".
          A newline character is written like "\n".

          the backslash character (\) is used as an escape character to indicate that the following character(s) should be treated specially. In this case, the "\n" sequence is an escape sequence that represents a newline character. The backslash before the n character tells the JavaScript interpreter that it should treat the n as a special character and not just as the letter "n".

          However, if we want to include an actual backslash character (\), we will have to escape it by using to two backslashes \\, or else with one single slash the JavaScript interpreter will still determines it as an special operator, Thus \\ will print \ on output.

          • But what about the quotation marks used within the quotation marks that wraps the string? Wouldn't JavaScript interpreter throw error?

            • In the given JavaScript string, the inner set of double quotation marks ("\\n") is escaped using a backslash (\) character. This tells the JavaScript interpreter to treat the inner double quotation marks as a regular character instead of a string delimiter.

              So when the string is rendered on output, the backslash character will be removed and the inner set of quotation marks will be displayed as a regular character. The rendered string will look like this,

              js
              '\n'
              '\n'

              The outer set of double quotation marks in the original string delimit the entire string and will be displayed as regular quotation marks.

          Source: ChatGPT CA (Code Analysis)

          + \ No newline at end of file diff --git a/javascript/notes/1/1-2.html b/javascript/notes/1/1-2.html index 7b0006f1..ef4284e1 100644 --- a/javascript/notes/1/1-2.html +++ b/javascript/notes/1/1-2.html @@ -5,14 +5,14 @@ 1-2 | Toshiki's Note - + - + - + - + @@ -35,8 +35,8 @@ -
          Skip to content

          - +
          Skip to content

          + \ No newline at end of file diff --git a/jp/index.html b/jp/index.html index 9d44b16a..38b1a9ef 100644 --- a/jp/index.html +++ b/jp/index.html @@ -5,14 +5,14 @@ 俊樹のノート | コンテンツ作成やメモ管理のための永遠のデジタル知識ベース - + - + - + - + @@ -35,8 +35,8 @@ -
          Skip to content

          俊樹のノート

          研究して作成

          👨‍💻 コンテンツ作成やメモ管理のための永遠のデジタル知識ベース

          Home logo
          - +
          Skip to content

          俊樹のノート

          研究して作成

          👨‍💻 コンテンツ作成やメモ管理のための永遠のデジタル知識ベース

          Home logo
          + \ No newline at end of file diff --git a/roadmap.html b/roadmap.html index 879b3084..4227d315 100644 --- a/roadmap.html +++ b/roadmap.html @@ -5,15 +5,15 @@ Theme | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
          Skip to content

          Theme

          Author:Anda Toshiki
          Updated:4 minutes ago
          Words:203
          Reading:1 min

          Homepage

          • Finish three hero action blocks with keywords and its corresponded descriptions.

          • Finish my learning platform section using SVGs of different online academies from simple icons.

            • Descriptions

            • Icon in SVG format

            • Platform name

            • Linkable SVG icon/button

              • Khan academy
              • GitHub
              • Libretext
              • OpenStax
              • BCcampus
              • Wikibooks
              • Wikipedia
              • Bookboon
              • [ ]

          Configs

          • Header configs including different properties and meta configs.
          • Complete navigation configuration.
          • Complete sidebar configs for different directories.
          • Vitepress sidebar generation plugin for huge bundled clips article directory.

          Articles

          • <head> tag documentation or guide by joshbuchea/HEAD.
          • Write index page for every directory, no Chat GPT allowed.
          • Chemistry review notes.
          • JavaScript 0-100 notes per chapter.
            • Marijn Haverbeke - Eloquent JavaScript_ A Modern Introduction to Programming (2011, No Starch Press)
          • Outliers novel clips
          • Migrate clipped articles and archives from Notion to Vitepress.
          • Fresh copy of "How To Ask Questions The Smart Way" by Eric Steven Raymond
          - +
          Skip to content

          Theme

          Author:Anda Toshiki
          Updated:2 minutes ago
          Words:203
          Reading:1 min

          Homepage

          • Finish three hero action blocks with keywords and its corresponded descriptions.

          • Finish my learning platform section using SVGs of different online academies from simple icons.

            • Descriptions

            • Icon in SVG format

            • Platform name

            • Linkable SVG icon/button

              • Khan academy
              • GitHub
              • Libretext
              • OpenStax
              • BCcampus
              • Wikibooks
              • Wikipedia
              • Bookboon
              • [ ]

          Configs

          • Header configs including different properties and meta configs.
          • Complete navigation configuration.
          • Complete sidebar configs for different directories.
          • Vitepress sidebar generation plugin for huge bundled clips article directory.

          Articles

          • <head> tag documentation or guide by joshbuchea/HEAD.
          • Write index page for every directory, no Chat GPT allowed.
          • Chemistry review notes.
          • JavaScript 0-100 notes per chapter.
            • Marijn Haverbeke - Eloquent JavaScript_ A Modern Introduction to Programming (2011, No Starch Press)
          • Outliers novel clips
          • Migrate clipped articles and archives from Notion to Vitepress.
          • Fresh copy of "How To Ask Questions The Smart Way" by Eric Steven Raymond
          + \ No newline at end of file diff --git a/save/reading/index.html b/save/reading/index.html index 3be6c427..ab350ee4 100644 --- a/save/reading/index.html +++ b/save/reading/index.html @@ -5,15 +5,15 @@ Welcome to Reading Notes | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
          Skip to content

          Welcome to Reading Notes

          Author:Anda Toshiki
          Updated:4 minutes ago
          Words:4
          Reading:1 min
          - +
          Skip to content

          Welcome to Reading Notes

          Author:Anda Toshiki
          Updated:2 minutes ago
          Words:4
          Reading:1 min
          + \ No newline at end of file diff --git a/save/reading/outliers/1.html b/save/reading/outliers/1.html index 0433ef56..3314ed7f 100644 --- a/save/reading/outliers/1.html +++ b/save/reading/outliers/1.html @@ -5,15 +5,15 @@ Introduction & Chapter 1: The Roseto Mystery | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
          Skip to content

          Introduction & Chapter 1: The Roseto Mystery

          Author:查尔斯
          Updated:4 minutes ago
          Words:1.4k
          Reading:8 min

          Summary: Introduction: The Roseto Mystery

          Section 1.

          In the late 1800s, immigrants from Roseto Valfortore, Italy, came to Pennsylvania to work in the slate quarry near the town of Bangor. The settlers established a new community, named after their old one: Roseto. They built schools, a park, small shops, and more than a dozen factories. They kept to themselves and did not interact much with the predominantly German and English populations of the towns around them.

          In the 1950s, a local doctor told Stewart Wolf, a medical researcher, that hardly anyone in Roseto under age sixty-five had heart disease. Wolf was curious. He did blood draws and EKG scans, and he analyzed physicians’ records and death certificates. Wolf was amazed that almost no one under fifty-five showed any signs of heart disease, which at the time was America’s leading cause of death in men under sixty-five. Wolf enlisted the help of John Bruhn, a sociologist. They found that there was no suicide, alcoholism, or drug addiction in Roseto: everyone seemed to be dying of old age. According to Gladwell, Roseto was an outlier.

          Section 2.

          Wolf was forced to rule out diet and lifestyle as explanations, because the Rosetans had poor eating habits, smoked heavily, and were obese. He ruled out genetics after determining that Rosetans’ relatives in other parts of the country were not in comparably good health. Wolf eventually decided that what made Roseto’s inhabitants so healthy was the town itself—its culture and social structure. Many homes contained three generations living together, and with a population of just two thousand people, there were twenty-two separate civic organizations.

          Wolf and Bruhn were met with a great deal of skepticism. They had to work hard to convince the medical establishment that the values of where we live and the people around us have a significant impact on who we are. Gladwell wants Outliers to do for our understanding of success what Wolf did for our understanding of health.

          Summary: Chapter One: The Matthew Effect

          Section 1.

          Gladwell describes a game between two teams in the Canadian Hockey League, the most competitive junior hockey league in the world. Starting at a very young age, players are regularly assessed for talent, so that the best can be separated out and prepared for the next level. The system is designed to be a meritocracy.

          Section 2.

          Gladwell wants to show that circumstances matter just as much for success as work ethic or intelligence. People often ask about the lifestyle, intelligence, or special talents of successful individuals, but not enough people ask when and where a person grew up. Gladwell likens people to trees: we all know that the tallest trees received the most sunlight, had nutrient-rich soil, and were lucky enough to avoid lumberjacks. He suggests that we study the environmental and social influences that make people successful.

          Section 3.

          In the 1980s, Canadian psychologist Roger Barnsley observed that on elite Canadian hockey teams, whether youth league or NHL, a disproportionate number of players have birthdays in the first three months of the year.

          Section 4.

          The explanation for the distribution of birthdays is simple: the cutoff date for an individual’s league assignment is January 1. A player born on January 2 will be 12 months older than one born at the end of December. At the age of nine or ten, this often translates into a huge difference in size, coordination, and maturity. By age ten, coaches regularly pick the oldest and largest potential players for the more competitive “rep squads,” where the players will receive better coaching, have more practice time, and play many more games. By thirteen or fourteen, all of the extra experience and coaching will have actually made the players better, and they will be selected for the more competitive league(s). The same thing happens in American youth baseball and European soccer, but with different cutoff dates.

          The phenomenon is also observable in education. Economists Kelly Bedard and Elizabeth Dhuey found that on math and science tests, the older children in fourth grade regularly score better than the youngest children. This can affect whether a child qualifies for a gifted program. When Bedard and Dhuey extended their analysis to four-year colleges, they found that the students who belonged to the relatively youngest group were underrepresented by more than 10 percent.

          Section 5.

          The top-level hockey players were given opportunities they neither deserved nor earned. Sociologist Robert Merton called this the “Matthew Effect,” after the verse in the Gospel of Matthew:

          “For unto everyone that hath shall be given, and he shall have abundance. But from that hath not shall be taken away even that which he hath.”

          The successful receive more resources: the best students receive the best teaching, the richest citizens get the biggest tax breaks, the largest kids get the best coaching. Sociologists call this “accumulative advantage.” Gladwell points out that cutoff dates exclude nearly half of the potential athletes from a population. Junior hockey teams in the Czech Republic show the same unbalanced distribution of birthdays as in Canada. If Canada or the Czech Republic separated each of their youth leagues into two separate leagues, one for kids born in the first half of the year, and one for kids born in the second half of the year, they would have twice as many athletes available for their national teams. Similarly, schools could separate kindergarten classes into students born in the first, middle, and last four months of the year. The benefits would justify the added administrative work, but, writes Gladwell, the scheme would run afoul of society’s need to believe that individual merit matters more than the rules society has created.

          Section 6.

          Gord Wasden, the father of one of the Canadian Hockey League boys from the first section, describes his son. Scott Wasden worked hard to get where he is, but he has also generally had the advantage of being big compared to others on his team. He was born on January 4.

          Analysis: Introduction: The Roseto Mystery & Chapter 1: The Matthew Effect

          Gladwell's thesis argues that that the idea of rugged, individual success is not accurate. Rather, the most successful person doesn’t thrive without some environmental and social influence plus a dose of good fortune.  After laying out the concepts of a meritocracy and suggesting that this is the way that hockey players advance in Canada, he immediately undercuts this idea. Gladwell uses the illustration of birthday distribution as an example of an invisible contributor to the success of hockey players. With a registration cutoff date of January 1, players born from January 2 through March 31 are older than teammates born later in the year. These older players are likely bigger, faster, more coordinated, and more mature. Since the older players are seen as more skilled, they get selected for more advanced leagues with more practice, more games, and higher-quality coaching. By the time these older players reach their early teens, the extra advantages gained from being judged better because of their birthday translate into being better players. Similarly, the age cutoff for school registrations often mistakes maturity for ability. As a result, the older children appear smarter, get put into advanced groups, and qualify for gifted programs. The birthdate bias carries through to college.

          Advantages result in more advantages. Gladwell reinforces this idea with the “Matthew Effect,” which states that "success leads to more success." More simply: by being a little bit better, a hockey player will get opportunities that may result in the player becoming an outlier. Gladwell implies that the systems that determine success are not efficient. He asks readers to question the way we, as a society, think about success. He suggests that changing the systems in athletics and education would chip away at the myth of individual merit as the chief marker of success and help level the playing field. Gladwell's model for this phenomenon is hockey player Scott Wasden. By demonstrating that Scott had the passion, talent, and work ethic for the game, as well as the good luck to be born on January 4, Gladwell reasons that Wasden, like many others he will be profiling, benefit by being both good and lucky.

          Reference

          • “Outliers Introduction & Chapter 1 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section1/.
          - +
          Skip to content

          Introduction & Chapter 1: The Roseto Mystery

          Author:查尔斯
          Updated:2 minutes ago
          Words:1.4k
          Reading:8 min

          Summary: Introduction: The Roseto Mystery

          Section 1.

          In the late 1800s, immigrants from Roseto Valfortore, Italy, came to Pennsylvania to work in the slate quarry near the town of Bangor. The settlers established a new community, named after their old one: Roseto. They built schools, a park, small shops, and more than a dozen factories. They kept to themselves and did not interact much with the predominantly German and English populations of the towns around them.

          In the 1950s, a local doctor told Stewart Wolf, a medical researcher, that hardly anyone in Roseto under age sixty-five had heart disease. Wolf was curious. He did blood draws and EKG scans, and he analyzed physicians’ records and death certificates. Wolf was amazed that almost no one under fifty-five showed any signs of heart disease, which at the time was America’s leading cause of death in men under sixty-five. Wolf enlisted the help of John Bruhn, a sociologist. They found that there was no suicide, alcoholism, or drug addiction in Roseto: everyone seemed to be dying of old age. According to Gladwell, Roseto was an outlier.

          Section 2.

          Wolf was forced to rule out diet and lifestyle as explanations, because the Rosetans had poor eating habits, smoked heavily, and were obese. He ruled out genetics after determining that Rosetans’ relatives in other parts of the country were not in comparably good health. Wolf eventually decided that what made Roseto’s inhabitants so healthy was the town itself—its culture and social structure. Many homes contained three generations living together, and with a population of just two thousand people, there were twenty-two separate civic organizations.

          Wolf and Bruhn were met with a great deal of skepticism. They had to work hard to convince the medical establishment that the values of where we live and the people around us have a significant impact on who we are. Gladwell wants Outliers to do for our understanding of success what Wolf did for our understanding of health.

          Summary: Chapter One: The Matthew Effect

          Section 1.

          Gladwell describes a game between two teams in the Canadian Hockey League, the most competitive junior hockey league in the world. Starting at a very young age, players are regularly assessed for talent, so that the best can be separated out and prepared for the next level. The system is designed to be a meritocracy.

          Section 2.

          Gladwell wants to show that circumstances matter just as much for success as work ethic or intelligence. People often ask about the lifestyle, intelligence, or special talents of successful individuals, but not enough people ask when and where a person grew up. Gladwell likens people to trees: we all know that the tallest trees received the most sunlight, had nutrient-rich soil, and were lucky enough to avoid lumberjacks. He suggests that we study the environmental and social influences that make people successful.

          Section 3.

          In the 1980s, Canadian psychologist Roger Barnsley observed that on elite Canadian hockey teams, whether youth league or NHL, a disproportionate number of players have birthdays in the first three months of the year.

          Section 4.

          The explanation for the distribution of birthdays is simple: the cutoff date for an individual’s league assignment is January 1. A player born on January 2 will be 12 months older than one born at the end of December. At the age of nine or ten, this often translates into a huge difference in size, coordination, and maturity. By age ten, coaches regularly pick the oldest and largest potential players for the more competitive “rep squads,” where the players will receive better coaching, have more practice time, and play many more games. By thirteen or fourteen, all of the extra experience and coaching will have actually made the players better, and they will be selected for the more competitive league(s). The same thing happens in American youth baseball and European soccer, but with different cutoff dates.

          The phenomenon is also observable in education. Economists Kelly Bedard and Elizabeth Dhuey found that on math and science tests, the older children in fourth grade regularly score better than the youngest children. This can affect whether a child qualifies for a gifted program. When Bedard and Dhuey extended their analysis to four-year colleges, they found that the students who belonged to the relatively youngest group were underrepresented by more than 10 percent.

          Section 5.

          The top-level hockey players were given opportunities they neither deserved nor earned. Sociologist Robert Merton called this the “Matthew Effect,” after the verse in the Gospel of Matthew:

          “For unto everyone that hath shall be given, and he shall have abundance. But from that hath not shall be taken away even that which he hath.”

          The successful receive more resources: the best students receive the best teaching, the richest citizens get the biggest tax breaks, the largest kids get the best coaching. Sociologists call this “accumulative advantage.” Gladwell points out that cutoff dates exclude nearly half of the potential athletes from a population. Junior hockey teams in the Czech Republic show the same unbalanced distribution of birthdays as in Canada. If Canada or the Czech Republic separated each of their youth leagues into two separate leagues, one for kids born in the first half of the year, and one for kids born in the second half of the year, they would have twice as many athletes available for their national teams. Similarly, schools could separate kindergarten classes into students born in the first, middle, and last four months of the year. The benefits would justify the added administrative work, but, writes Gladwell, the scheme would run afoul of society’s need to believe that individual merit matters more than the rules society has created.

          Section 6.

          Gord Wasden, the father of one of the Canadian Hockey League boys from the first section, describes his son. Scott Wasden worked hard to get where he is, but he has also generally had the advantage of being big compared to others on his team. He was born on January 4.

          Analysis: Introduction: The Roseto Mystery & Chapter 1: The Matthew Effect

          Gladwell's thesis argues that that the idea of rugged, individual success is not accurate. Rather, the most successful person doesn’t thrive without some environmental and social influence plus a dose of good fortune.  After laying out the concepts of a meritocracy and suggesting that this is the way that hockey players advance in Canada, he immediately undercuts this idea. Gladwell uses the illustration of birthday distribution as an example of an invisible contributor to the success of hockey players. With a registration cutoff date of January 1, players born from January 2 through March 31 are older than teammates born later in the year. These older players are likely bigger, faster, more coordinated, and more mature. Since the older players are seen as more skilled, they get selected for more advanced leagues with more practice, more games, and higher-quality coaching. By the time these older players reach their early teens, the extra advantages gained from being judged better because of their birthday translate into being better players. Similarly, the age cutoff for school registrations often mistakes maturity for ability. As a result, the older children appear smarter, get put into advanced groups, and qualify for gifted programs. The birthdate bias carries through to college.

          Advantages result in more advantages. Gladwell reinforces this idea with the “Matthew Effect,” which states that "success leads to more success." More simply: by being a little bit better, a hockey player will get opportunities that may result in the player becoming an outlier. Gladwell implies that the systems that determine success are not efficient. He asks readers to question the way we, as a society, think about success. He suggests that changing the systems in athletics and education would chip away at the myth of individual merit as the chief marker of success and help level the playing field. Gladwell's model for this phenomenon is hockey player Scott Wasden. By demonstrating that Scott had the passion, talent, and work ethic for the game, as well as the good luck to be born on January 4, Gladwell reasons that Wasden, like many others he will be profiling, benefit by being both good and lucky.

          Reference

          • “Outliers Introduction & Chapter 1 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section1/.
          + \ No newline at end of file diff --git a/save/reading/outliers/2.html b/save/reading/outliers/2.html index df15b8b0..fb38bd54 100644 --- a/save/reading/outliers/2.html +++ b/save/reading/outliers/2.html @@ -5,15 +5,15 @@ Chapter Two: The 10,000-Hour Rule | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
          Skip to content

          Chapter Two: The 10,000-Hour Rule

          Author:Anda Toshiki
          Updated:4 minutes ago
          Words:1.4k
          Reading:8 min

          Summary: Chapter Two: The 10,000-Hour Rule

          Section 1.

          Bill Joy, a co-founder of Sun Microsystems, is one of the most influential computer programmers of all time. Joy attended the University of Michigan, thinking to become a biologist or mathematician, but he became obsessed with the Computer Center that opened during his freshman year. In 1975, he enrolled in graduate school at UC Berkeley. At both schools, Bill Joy spent much of his free time programming. After graduating from Berkeley, he founded Sun Microsystems, eventually rewriting the Java programming language. He would appear to be a good example of success based on individual merit.

          Section 2.

          If achievement is the combination of talent and preparation, how much does innate talent affect one’s success? In the 1990s, a study at Berlin’s elite Academy of Music determined that, regardless of instrument, all of the world-class students had practiced more than 10,000 hours. They did not find anyone at the top level who spent less time, nor did they find anyone who spent that amount of time who was not successful. Neurologist Daniel Levitin states that, across many fields, world-class expertise is never accomplished in less than 10,000 hours. The law holds even for a prodigy like Mozart, who started composing at age six: he did not compose his first masterwork until he was twenty-one. The youth athletes from the previous chapter who made it to the professional level put in 10,000 hours of practice. And note: individuals cannot normally put in that much practice without help. Most people will need supportive parents, financial stability, and probably a special program—like an all-star youth hockey team.

          Section 3.

          Bill Joy was certainly intelligent, having achieved a perfect score on the math portion of his Scholastic Aptitude Test. His opportunities, however, were extraordinary. Bill Joy happened to choose a college that had a time-sharing computer available, something that was exceedingly rare during the early 1970s. While most students had to pay for computer time, Bill Joy exploited a bug in the college’s system to gain unlimited access to the Computer Center, which was walking distance from where he lived. He was able to spend almost all of his free time programming, and when he went to Berkeley, he had a terminal at home, where he could program until he fell asleep at his keyboard. Bill Joy was able to accumulate 10,000 hours while in college.

          Section 4.

          The Beatles are another example of the 10,000-hours principle. In 1960, when they were still a high school rock band, they were given the chance to travel to Hamburg, Germany and play in various strip clubs. The Beatles were contracted to play for hours every night, seven nights a week, and thereby were forced to develop as musicians. After a year and a half, they had performed 270 nights. By 1964, when they first found commercial success, they had performed an estimated twelve hundred times—more than most band bands do in an entire career.

          Section 5.

          Born in Seattle to affluent parents, Bill Gates was sent to a private school for seventh grade. The school’s Mother’s Club funded the purchase of a time-sharing terminal connected to a mainframe computer in Seattle. As an eighth-grader, Gates was able to start programming. When the Mother’s Club could no longer pay for computing time, Gates was able to continue programming at Information Sciences, Inc. (ISI) through a connection he made with one of the school parents. After that, one of ISI’s founders recommended Gates for a programming project at the Bonneville Power station. Gates was able to leave high school during his senior year to program for the Bonneville Power station as an independent study project. By the time Bill Gates dropped out of Harvard, he was well past 10,000 hours of experience.

          Section 6.

          In a list of the seventy-five richest people in human history, going as far back as ancient Egypt and converting all wealth estimates into modern U.S. dollars, fourteen names are Americans born within nine years of one another (including John D. Rockefeller and J.P. Morgan). What accounts for the fact that a list that covers thousands of years should have 20 percent of its members so close together? The fourteen Americans happened to live during the 1860s and 1870s, when the American economy was undergoing a huge transformation: the expansion of the railroads and the creation of Wall Street. Gladwell argues that the fourteen names are so close in birth date because they were all the perfect age to seize the opportunities available.

          Bill Joy and Bill Gates were also born at just the right time. In 1975, Popular Electronics ran a cover story about the Altair 8800, a $397 microcomputer kit. Someone born before 1954 would likely already have a job with IBM, working on mainframes. Someone born after 1956 would likely still be in high school. Most of the biggest pioneers in the modern computer industry, including Bill Gates, Bill Joy, Steve Jobs, and Eric Schmidt, were born in 1954 or 1955, as were Joy’s three fellow founders at Sun.

          Analysis: Chapter Two: The 10,000-Hour Rule

          Gladwell introduces his controversial and widely disputed 10,000 hours rule. Simply put, the rule suggests that to master a skill, an individual needs to practice it for 10,000 hours. Gladwell argues that, like hockey, success in computing requires both skill and luck, rather than pure, simple, natural ability. Gladwell's example is situated at the University of Michigan, specifically the new computer center, in 1971. The story of Bill Joy undermines the idea of success as an inexplicable, miraculous accomplishment. Though Gladwell agrees Joy is bright and talented, Joy also lucks into several happy accidents that allow for increased access. These strokes of luck give Joy the opportunity to become a computer expert. Gladwell's use of a psychological study conducted at the Academy of Music in Berlin, Germany, in the early 1990s forms the crux of his argument in this chapter. However, critics have suggested that this study was flawed and that there is no incontrovertible evidence to suggest that doing anything for 10,000 hours guarantees mastery. Rather, practice is, as Gladwell points out elsewhere throughout the text, just one of the factors in success. However, he also correlates the familial and economic advantages necessary to reach 10,000 of practice time, reinforcing the larger thesis of the book.

          Gladwell argues that the Beatles and Bill Gates are examples of his notion of time spent directly relating to mastery. While detailing how the Beatles reached the 10,000-hour threshold for mastery, Gladwell also highlights the lucky breaks they had in achieving success, like the connection that landed the band in Hamburg’s music scene. Additionally, while Gates has become something of an American folk hero, Gladwell argues that Gates did not reach his great achievements completely on his own. His wealthy family, his lucky interaction with a computer in 1968, and his college experience allowed him far greater access to opportunity. Without this combination of factors, along with his intelligence and drive, Gates would likely not have become a household name. Again, Gladwell reinforces the idea that success comes not only from being good, but from having no small amount of luck, whether that be time, money, or, in an echo of the hockey player example, birthdate.

          Gladwell claims that one important factor of success is the year in which one is born. In terms of wealth, there are 14 Americans, born in a nine-year period of the 1800s, who are among the richest people in history. This suggests that there was some connection to when they were born and the opportunities available to them in terms of innovation and invention, as well as the position they were in to take advantage of the opportunities. Similarly, men born in the same era of Bill Gates were coming of age at the bleeding edge of technology. Proximity to social and technological change, as well as the wealth and connections to take advantage of it, put these men in an advantageous position. Being in the right place at the right time, Gladwell argues, has at least as much to do with success as one's inborn abilities.

          Reference

          • “Outliers Chapter 2 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section2/. Accessed 27 Feb. 2023.
          - +
          Skip to content

          Chapter Two: The 10,000-Hour Rule

          Author:Anda Toshiki
          Updated:2 minutes ago
          Words:1.4k
          Reading:8 min

          Summary: Chapter Two: The 10,000-Hour Rule

          Section 1.

          Bill Joy, a co-founder of Sun Microsystems, is one of the most influential computer programmers of all time. Joy attended the University of Michigan, thinking to become a biologist or mathematician, but he became obsessed with the Computer Center that opened during his freshman year. In 1975, he enrolled in graduate school at UC Berkeley. At both schools, Bill Joy spent much of his free time programming. After graduating from Berkeley, he founded Sun Microsystems, eventually rewriting the Java programming language. He would appear to be a good example of success based on individual merit.

          Section 2.

          If achievement is the combination of talent and preparation, how much does innate talent affect one’s success? In the 1990s, a study at Berlin’s elite Academy of Music determined that, regardless of instrument, all of the world-class students had practiced more than 10,000 hours. They did not find anyone at the top level who spent less time, nor did they find anyone who spent that amount of time who was not successful. Neurologist Daniel Levitin states that, across many fields, world-class expertise is never accomplished in less than 10,000 hours. The law holds even for a prodigy like Mozart, who started composing at age six: he did not compose his first masterwork until he was twenty-one. The youth athletes from the previous chapter who made it to the professional level put in 10,000 hours of practice. And note: individuals cannot normally put in that much practice without help. Most people will need supportive parents, financial stability, and probably a special program—like an all-star youth hockey team.

          Section 3.

          Bill Joy was certainly intelligent, having achieved a perfect score on the math portion of his Scholastic Aptitude Test. His opportunities, however, were extraordinary. Bill Joy happened to choose a college that had a time-sharing computer available, something that was exceedingly rare during the early 1970s. While most students had to pay for computer time, Bill Joy exploited a bug in the college’s system to gain unlimited access to the Computer Center, which was walking distance from where he lived. He was able to spend almost all of his free time programming, and when he went to Berkeley, he had a terminal at home, where he could program until he fell asleep at his keyboard. Bill Joy was able to accumulate 10,000 hours while in college.

          Section 4.

          The Beatles are another example of the 10,000-hours principle. In 1960, when they were still a high school rock band, they were given the chance to travel to Hamburg, Germany and play in various strip clubs. The Beatles were contracted to play for hours every night, seven nights a week, and thereby were forced to develop as musicians. After a year and a half, they had performed 270 nights. By 1964, when they first found commercial success, they had performed an estimated twelve hundred times—more than most band bands do in an entire career.

          Section 5.

          Born in Seattle to affluent parents, Bill Gates was sent to a private school for seventh grade. The school’s Mother’s Club funded the purchase of a time-sharing terminal connected to a mainframe computer in Seattle. As an eighth-grader, Gates was able to start programming. When the Mother’s Club could no longer pay for computing time, Gates was able to continue programming at Information Sciences, Inc. (ISI) through a connection he made with one of the school parents. After that, one of ISI’s founders recommended Gates for a programming project at the Bonneville Power station. Gates was able to leave high school during his senior year to program for the Bonneville Power station as an independent study project. By the time Bill Gates dropped out of Harvard, he was well past 10,000 hours of experience.

          Section 6.

          In a list of the seventy-five richest people in human history, going as far back as ancient Egypt and converting all wealth estimates into modern U.S. dollars, fourteen names are Americans born within nine years of one another (including John D. Rockefeller and J.P. Morgan). What accounts for the fact that a list that covers thousands of years should have 20 percent of its members so close together? The fourteen Americans happened to live during the 1860s and 1870s, when the American economy was undergoing a huge transformation: the expansion of the railroads and the creation of Wall Street. Gladwell argues that the fourteen names are so close in birth date because they were all the perfect age to seize the opportunities available.

          Bill Joy and Bill Gates were also born at just the right time. In 1975, Popular Electronics ran a cover story about the Altair 8800, a $397 microcomputer kit. Someone born before 1954 would likely already have a job with IBM, working on mainframes. Someone born after 1956 would likely still be in high school. Most of the biggest pioneers in the modern computer industry, including Bill Gates, Bill Joy, Steve Jobs, and Eric Schmidt, were born in 1954 or 1955, as were Joy’s three fellow founders at Sun.

          Analysis: Chapter Two: The 10,000-Hour Rule

          Gladwell introduces his controversial and widely disputed 10,000 hours rule. Simply put, the rule suggests that to master a skill, an individual needs to practice it for 10,000 hours. Gladwell argues that, like hockey, success in computing requires both skill and luck, rather than pure, simple, natural ability. Gladwell's example is situated at the University of Michigan, specifically the new computer center, in 1971. The story of Bill Joy undermines the idea of success as an inexplicable, miraculous accomplishment. Though Gladwell agrees Joy is bright and talented, Joy also lucks into several happy accidents that allow for increased access. These strokes of luck give Joy the opportunity to become a computer expert. Gladwell's use of a psychological study conducted at the Academy of Music in Berlin, Germany, in the early 1990s forms the crux of his argument in this chapter. However, critics have suggested that this study was flawed and that there is no incontrovertible evidence to suggest that doing anything for 10,000 hours guarantees mastery. Rather, practice is, as Gladwell points out elsewhere throughout the text, just one of the factors in success. However, he also correlates the familial and economic advantages necessary to reach 10,000 of practice time, reinforcing the larger thesis of the book.

          Gladwell argues that the Beatles and Bill Gates are examples of his notion of time spent directly relating to mastery. While detailing how the Beatles reached the 10,000-hour threshold for mastery, Gladwell also highlights the lucky breaks they had in achieving success, like the connection that landed the band in Hamburg’s music scene. Additionally, while Gates has become something of an American folk hero, Gladwell argues that Gates did not reach his great achievements completely on his own. His wealthy family, his lucky interaction with a computer in 1968, and his college experience allowed him far greater access to opportunity. Without this combination of factors, along with his intelligence and drive, Gates would likely not have become a household name. Again, Gladwell reinforces the idea that success comes not only from being good, but from having no small amount of luck, whether that be time, money, or, in an echo of the hockey player example, birthdate.

          Gladwell claims that one important factor of success is the year in which one is born. In terms of wealth, there are 14 Americans, born in a nine-year period of the 1800s, who are among the richest people in history. This suggests that there was some connection to when they were born and the opportunities available to them in terms of innovation and invention, as well as the position they were in to take advantage of the opportunities. Similarly, men born in the same era of Bill Gates were coming of age at the bleeding edge of technology. Proximity to social and technological change, as well as the wealth and connections to take advantage of it, put these men in an advantageous position. Being in the right place at the right time, Gladwell argues, has at least as much to do with success as one's inborn abilities.

          Reference

          • “Outliers Chapter 2 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section2/. Accessed 27 Feb. 2023.
          + \ No newline at end of file diff --git a/save/reading/outliers/3.html b/save/reading/outliers/3.html index 4c66f03b..c5a26435 100644 --- a/save/reading/outliers/3.html +++ b/save/reading/outliers/3.html @@ -5,15 +5,15 @@ Chapter 3: The Trouble with Geniuses, Part 1 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
          Skip to content

          Chapter 3: The Trouble with Geniuses, Part 1

          Author:Anda Toshiki
          Updated:4 minutes ago
          Words:1.1k
          Reading:6 min

          Summary: Chapter Three: The Trouble with Geniuses, Part 1

          Section 1.

          Chris Langan appeared on the television trivia show 1 vs. 100 after being the subject of interviews and at least one documentary, due to his extremely high IQ. He had little difficulty in high school, got a perfect score on his SAT, and read through Principia Mathematica as a teenager. On 1 vs. 100, Langan cashed out with winnings of $250,000.

          Section 2.

          Shortly after World War I, Lewis Terman, creator of the widely used Stanford-Binet IQ test, became fascinated with child prodigies. In 1921, he identified exceptionally gifted 1,470 students who came to be known as the “Termites.” Terman kept track of them over the years, carefully cataloging their educational achievement, marriages, psychological health, and employment. Terman was sure that the Termites would be the future elite of the United States. The same confidence underlies the use of IQ-like tests, such as the SAT, to assess applicants at Ivy League schools and corporations such as Microsoft and Google. Gladwell states that Terman was wrong about the Termites, and if he had met Chris Langan as a teenager, he would have been wrong about him, too.

          Section 3.

          Gladwell gives two examples—one easy and one much harder—of questions that use visual puzzles to test IQ, without requiring any language abilities or specific factual knowledge. The average human will score 100. Those scoring below 70 are considered mentally disabled, and those who are successful in graduate programs likely have an IQ of 115 or higher. According to Gladwell, however, above 120 IQ makes little or no difference to success. A similar point applies to basketball: height is certainly an advantage, but there is, at best, modest value in being six foot seven instead of six foot six. A basketball player just needs to be tall enough.

          A list of the last twenty-five Americans to win a Nobel Prize in Medicine includes graduates of prestigious schools, such as Columbia, Harvard, and MIT, but also graduates of DePauw, Holy Cross, and Gettysburg College. Similarly, there have been American Nobel laureates in Chemistry from Harvard and MIT, but also from Notre Dame and the University of Illinois. Harvard might have more intelligent students, but many other colleges have students smart enough to win a Nobel.

          At the University of Michigan law school, around 10 percent of students are racial minorities. Without affirmative action, there would be less than 3 percent. Looking at career performance after graduation, Michigan found no difference between white and minority graduates. Minority students come into law school with weaker academic credentials than their white counterparts, but they are above the threshold required to be just as successful.

          Section 4.

          Not all questions that test for intelligence have a single correct answer. A different sort of question might ask for a list of different uses for a brick, or a blanket. A question like this measures imagination and creativity. At a top British high school, one student lists more than ten uses, many of which are comical. Another student, a prodigy with one of the school’s highest IQs, lists just a few uses, all of which are practical. Compared to an IQ test, asking about different uses for a brick might be a better way to identify future Nobel Prize winners.

          Section 5.

          Terman’s error was using intelligence alone to choose his Termites. While some of the Termites had successful careers, an unexpectedly high went on to careers that even Terman didn’t consider to be successful. The two students tested by Terman’s team who actually did go on to win Nobels were not selected as Termites: their IQs were too low. Terman eventually concluded that “intellect and achievement are far from perfectly correlated.”

          Gladwell states that to understand Chris Langan’s prospects of becoming a “true outlier,” one must learn more about him.

          Analysis: Chapter Three: The Trouble with Geniuses, Part 1

          Intelligence, Gladwell argues, does not equal success. He dedicates this chapter to the examination of geniuses. Comparing the young subjects of Lewis Terman to Chris Langan, Gladwell argues against Terman’s idea that genius is a key to societal advancement. Gladwell lists Langan’s early accomplishments as a shining example of Terman's idea, then swiftly undercuts expectations. Gladwell argues again that individuals do not succeed or fail solely on their own, but rather due to a constellation of factors, many of which are uncontrollable. Langan's early achievements would suggest great things and a continued path toward accomplishment, but Gladwell includes the anecdote of his game show appearance to undermine the notion that genius equals success. Using two questions from an IQ test, Gladwell introduces the idea of an IQ threshold to examine the the larger notion of intelligence and its limitations. Arguing that the measure of someone’s intelligence is only helpful up to a point, Gladwell uses examples of schools that Nobel laureates attended for undergraduate studies. Some, he points out, are elite institutions; others are not. Additionally, he points to success among graduates of the law school at the University of Michigan. There was no quantifiable difference in success post-graduation between white and POC students, some of whom were admitted under affirmative action with slightly lower undergraduate grades and standardized test scores. Reasonably, then, the level of intelligence beyond a certain point is moot. All of the students were intelligent enough to graduate, and beyond that, he argues, their intelligence predicted nothing.

          Elements other than intelligence must contribute to success. Gladwell expands on his notion of an intelligence threshold and examines these other factors through an example of a question on a divergence test. Using examples of two students at an elite British school, Gladwell shows that the divergence test has no right answers, but instead looks for answers that demonstrate uniqueness and creativity. Intelligence matters, but so does imagination, creativity, and outside-the-box thinking. Gladwell circles back to Terman, reinforcing that the error when choosing his Termites was a focus on intelligence alone. He once again turns his attention to Chris Langan, foreshadowing that Langan’s story did not follow a direct line to achievement. Intelligence alone does not offer a certain path to success.

          Reference

          • “Outliers Chapter 3 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section3/. Accessed 27 Feb. 2023.
          - +
          Skip to content

          Chapter 3: The Trouble with Geniuses, Part 1

          Author:Anda Toshiki
          Updated:2 minutes ago
          Words:1.1k
          Reading:6 min

          Summary: Chapter Three: The Trouble with Geniuses, Part 1

          Section 1.

          Chris Langan appeared on the television trivia show 1 vs. 100 after being the subject of interviews and at least one documentary, due to his extremely high IQ. He had little difficulty in high school, got a perfect score on his SAT, and read through Principia Mathematica as a teenager. On 1 vs. 100, Langan cashed out with winnings of $250,000.

          Section 2.

          Shortly after World War I, Lewis Terman, creator of the widely used Stanford-Binet IQ test, became fascinated with child prodigies. In 1921, he identified exceptionally gifted 1,470 students who came to be known as the “Termites.” Terman kept track of them over the years, carefully cataloging their educational achievement, marriages, psychological health, and employment. Terman was sure that the Termites would be the future elite of the United States. The same confidence underlies the use of IQ-like tests, such as the SAT, to assess applicants at Ivy League schools and corporations such as Microsoft and Google. Gladwell states that Terman was wrong about the Termites, and if he had met Chris Langan as a teenager, he would have been wrong about him, too.

          Section 3.

          Gladwell gives two examples—one easy and one much harder—of questions that use visual puzzles to test IQ, without requiring any language abilities or specific factual knowledge. The average human will score 100. Those scoring below 70 are considered mentally disabled, and those who are successful in graduate programs likely have an IQ of 115 or higher. According to Gladwell, however, above 120 IQ makes little or no difference to success. A similar point applies to basketball: height is certainly an advantage, but there is, at best, modest value in being six foot seven instead of six foot six. A basketball player just needs to be tall enough.

          A list of the last twenty-five Americans to win a Nobel Prize in Medicine includes graduates of prestigious schools, such as Columbia, Harvard, and MIT, but also graduates of DePauw, Holy Cross, and Gettysburg College. Similarly, there have been American Nobel laureates in Chemistry from Harvard and MIT, but also from Notre Dame and the University of Illinois. Harvard might have more intelligent students, but many other colleges have students smart enough to win a Nobel.

          At the University of Michigan law school, around 10 percent of students are racial minorities. Without affirmative action, there would be less than 3 percent. Looking at career performance after graduation, Michigan found no difference between white and minority graduates. Minority students come into law school with weaker academic credentials than their white counterparts, but they are above the threshold required to be just as successful.

          Section 4.

          Not all questions that test for intelligence have a single correct answer. A different sort of question might ask for a list of different uses for a brick, or a blanket. A question like this measures imagination and creativity. At a top British high school, one student lists more than ten uses, many of which are comical. Another student, a prodigy with one of the school’s highest IQs, lists just a few uses, all of which are practical. Compared to an IQ test, asking about different uses for a brick might be a better way to identify future Nobel Prize winners.

          Section 5.

          Terman’s error was using intelligence alone to choose his Termites. While some of the Termites had successful careers, an unexpectedly high went on to careers that even Terman didn’t consider to be successful. The two students tested by Terman’s team who actually did go on to win Nobels were not selected as Termites: their IQs were too low. Terman eventually concluded that “intellect and achievement are far from perfectly correlated.”

          Gladwell states that to understand Chris Langan’s prospects of becoming a “true outlier,” one must learn more about him.

          Analysis: Chapter Three: The Trouble with Geniuses, Part 1

          Intelligence, Gladwell argues, does not equal success. He dedicates this chapter to the examination of geniuses. Comparing the young subjects of Lewis Terman to Chris Langan, Gladwell argues against Terman’s idea that genius is a key to societal advancement. Gladwell lists Langan’s early accomplishments as a shining example of Terman's idea, then swiftly undercuts expectations. Gladwell argues again that individuals do not succeed or fail solely on their own, but rather due to a constellation of factors, many of which are uncontrollable. Langan's early achievements would suggest great things and a continued path toward accomplishment, but Gladwell includes the anecdote of his game show appearance to undermine the notion that genius equals success. Using two questions from an IQ test, Gladwell introduces the idea of an IQ threshold to examine the the larger notion of intelligence and its limitations. Arguing that the measure of someone’s intelligence is only helpful up to a point, Gladwell uses examples of schools that Nobel laureates attended for undergraduate studies. Some, he points out, are elite institutions; others are not. Additionally, he points to success among graduates of the law school at the University of Michigan. There was no quantifiable difference in success post-graduation between white and POC students, some of whom were admitted under affirmative action with slightly lower undergraduate grades and standardized test scores. Reasonably, then, the level of intelligence beyond a certain point is moot. All of the students were intelligent enough to graduate, and beyond that, he argues, their intelligence predicted nothing.

          Elements other than intelligence must contribute to success. Gladwell expands on his notion of an intelligence threshold and examines these other factors through an example of a question on a divergence test. Using examples of two students at an elite British school, Gladwell shows that the divergence test has no right answers, but instead looks for answers that demonstrate uniqueness and creativity. Intelligence matters, but so does imagination, creativity, and outside-the-box thinking. Gladwell circles back to Terman, reinforcing that the error when choosing his Termites was a focus on intelligence alone. He once again turns his attention to Chris Langan, foreshadowing that Langan’s story did not follow a direct line to achievement. Intelligence alone does not offer a certain path to success.

          Reference

          • “Outliers Chapter 3 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section3/. Accessed 27 Feb. 2023.
          + \ No newline at end of file diff --git a/save/reading/outliers/4.html b/save/reading/outliers/4.html index 657e3510..a3d43e39 100644 --- a/save/reading/outliers/4.html +++ b/save/reading/outliers/4.html @@ -5,15 +5,15 @@ Chapter 4: The Trouble with Geniuses, Part 2 | Toshiki's Note - + - + - + - + @@ -36,8 +36,8 @@ -
          Skip to content

          Chapter 4: The Trouble with Geniuses, Part 2

          Author:Anda Toshiki
          Updated:4 minutes ago
          Words:1.3k
          Reading:8 min

          Summary: Chapter Four: The Trouble with Geniuses, Part 2

          Section 1.

          Chris Langan’s mother had four children, all from different fathers. Her first husband died in Mexico, the second was murdered, the third committed suicide, and the fourth was an abusive alcoholic. Langan says he has never met someone who grew up as impoverished as he and his brothers did. Attending Reed College, in Oregon, on a scholarship, he felt as though he did not belong with the rest of the students. When his mother neglected to fill out the financial aid forms, he lost his scholarship and dropped out. According to Langan, the school just did not care about their students. Later, Langan attended Montana State University in Bozeman but he dropped out when a dean refused Langan’s request to adjust his class schedule because of car trouble. He still has intellectual interests and has been working on a treatise called the “Cognitive Theoretic Model of the Universe.” When asked if, hypothetically, he would take a position at Harvard, he acknowledges the benefit of an environment with so much intellectual energy, but he worries about a lack of intellectual freedom.

          Section 2.

          Gladwell points out the oddity of Langan’s experiences. Most colleges, especially small ones, try to accommodate student needs. Smart people take positions at places like Harvard instead of in the private sector precisely for the added intellectual freedom. Gladwell contrasts Langan’s story with Robert Oppenheimer’s. While at Cambridge, Oppenheimer became frustrated with his tutor and tried to poison him. After negotiations with the school administration, Oppenheimer was put on probation and assigned to a psychiatrist. Whereas Langan dropped out after his mother failed to fill out paperwork, Oppenheimer managed to stay in college after trying to kill someone. Later, Oppenheimer convinced General Leslie Groves to make Oppenheimer the scientific director of the Manhattan Project. Oppenheimer had the ability to persuade people, where Langan did not.

          Section 3.

          Psychologist Robert Sternberg calls the ability to persuade someone “practical intelligence.” It involves knowing what to say, how to say it, and when. It requires an ability to read situations. Individuals can have either practical or analytical intelligence, or in the case of Oppenheimer, both. To understand where one obtains practical intelligence, Gladwell refers to a study conducted by Annette Lareau.

          Lareau observed parenting strategies in both Black and white families from different socioeconomic strata. She found two distinct strategies: “concerted cultivation” and “accomplishment of natural growth.” Concerted cultivation, most common in middle-class and wealthier families, is defined by parents’ active promotion of their children’s talents and interests. Accomplishment of natural growth, most common in working-class or impoverished families, is defined by parents’ lack of interest or interaction in their children’s free time. Concerted cultivation, writes Gladwell, encourages children to seek opportunities for growth and to advocate for themselves. Accomplishment of natural growth leaves children unprepared to shape their environment for their own benefit. Concerted cultivation fosters an attitude better suited for success in the modern world.

          Section 4.

          Oppenheimer was raised by affluent parents who sent him to a progressive private school and took an active interest in his hobbies.

          • Affluent: Having an abundant supply of money or possessions of value.

          By contrast, Chris Langan’s brother Mark states that as children, they learned to resent authority. Mark, too, was unable to obtain financial aid, because he had no knowledge of how the system worked. If Chris Langan had been raised in a family that valued education, he probably would have had more success.

          Section 5.

          Once the Termites reached working adulthood, Terman grouped 730 of the males into three categories, based on their levels of success. The top 20 percent were upper-class professionals, while the bottom 20 percent had low-paying jobs or were unemployed. After analyzing the differences between the groups, Terman found that the bottom 20 percent came almost entirely from the lowest social and economic classes. What they lacked was “a community around them that prepared them properly for the world.”

          Section 6.

          Chris Langan lives on a horse farm in Missouri, where he still writes. He is happily married and continues to read physics and philosophy. While he has spent decades on his writing, almost none of it has ever been published. Langan admits he has not tried to contact publishers or found an agent—and does not plan to. Chris Langan did not have the support necessary to meet success. Gladwell points that no one ever makes it alone, regardless of if they are successful musicians, athletes, tech billionaires, or geniuses.

          Analysis: Chapter Four: The Trouble with Geniuses, Part 2

          Family background plays a crucial role in an individual’s success. While a genius like Chris Langan should thrive on a college campus, he drops out. Langan doesn’t struggle with academics, but with paperwork, procedures, and environment. Gladwell’s characterization of Langan almost makes him seem like two separate characters: a confident, genius game show contestant versus a child from a poor and troubled family. Langan may be a true outlier in the sense that he doesn’t seem to fit in academia or the working-class world.  Langan’s story is ironic. His brilliant mind should propel him to success. However, his story also perfectly proves Gladwell’s point that brainpower alone does not lead to success. The author delves deeper into the irony of Langan’s situation by comparing him to Robert Oppenheimer, who worked on the nuclear bomb during World War II. Like Langan, Oppenheimer possesses great intelligence. Unlike Langan, Oppenheimer has an understanding that allows him to navigate the world effectively. Oppenheimer knows how to combat challenges, where Langan gets bested by a financial aid problem and class schedule. Oppenheimer’s family background gave him the confidence to deal with authority while Langan’s upbringing created a distrust of authority. Without a family background that encourages success, intelligence is not enough.

          Contrast & Comparison

          Oppenheimer’s family background gave him the confidence to deal with authority while Langan’s upbringing created a distrust of authority.

          The power of persuasion is an important factor that drives success. Gladwell notes that the power of persuasion is practical intelligence. He contrasts practical intelligence with analytical ability, noting that just because a person is smart does not mean they have practical intelligence. These two types of knowledge are not necessarily coeval. He reinforces this point with a return to the comparison of Langan and Oppenheimer. Both men are exceedingly intelligent, but Langan lacks the social savvy of practical intelligence. Gladwell suggests that individuals gain practical intelligence skills from their families, discussing a study by sociologist Annette Lareau to prove his point. Children from wealthier families learn how to interact with society in a way that drives achievement. Successful people have the power of persuasion and can convince others to see things from their point of view.

          Success, then, depends on more than individual effort. Gladwell builds this argument by detailing the differences between Oppenheimer’s upbringing and Langan’s. Oppenheimer lived in an upper-class neighborhood with myriad advantages. He learned how to negotiate and stand up for himself. Langan’s family moved from place to place, struggling for jobs, money, food, and clothes, and Langan learned that he couldn’t rely on others. Gladwell's consideration of the Termites' success or struggles as adults supports his assertion that success is more than an individual effort; Gladwell states, “In the end, only one thing mattered: family background.” Terman’s findings and Gladwell’s conclusion do not mean that talented individuals from lower social and economic classes cannot have successful futures. To succeed, everyone needs help along the way, if not from family, then from a supportive community. Individuals do not achieve success solely on their own.

          Reference

          • “Outliers Chapter 4 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section4/.
          - +
          Skip to content

          Chapter 4: The Trouble with Geniuses, Part 2

          Author:Anda Toshiki
          Updated:2 minutes ago
          Words:1.3k
          Reading:8 min

          Summary: Chapter Four: The Trouble with Geniuses, Part 2

          Section 1.

          Chris Langan’s mother had four children, all from different fathers. Her first husband died in Mexico, the second was murdered, the third committed suicide, and the fourth was an abusive alcoholic. Langan says he has never met someone who grew up as impoverished as he and his brothers did. Attending Reed College, in Oregon, on a scholarship, he felt as though he did not belong with the rest of the students. When his mother neglected to fill out the financial aid forms, he lost his scholarship and dropped out. According to Langan, the school just did not care about their students. Later, Langan attended Montana State University in Bozeman but he dropped out when a dean refused Langan’s request to adjust his class schedule because of car trouble. He still has intellectual interests and has been working on a treatise called the “Cognitive Theoretic Model of the Universe.” When asked if, hypothetically, he would take a position at Harvard, he acknowledges the benefit of an environment with so much intellectual energy, but he worries about a lack of intellectual freedom.

          Section 2.

          Gladwell points out the oddity of Langan’s experiences. Most colleges, especially small ones, try to accommodate student needs. Smart people take positions at places like Harvard instead of in the private sector precisely for the added intellectual freedom. Gladwell contrasts Langan’s story with Robert Oppenheimer’s. While at Cambridge, Oppenheimer became frustrated with his tutor and tried to poison him. After negotiations with the school administration, Oppenheimer was put on probation and assigned to a psychiatrist. Whereas Langan dropped out after his mother failed to fill out paperwork, Oppenheimer managed to stay in college after trying to kill someone. Later, Oppenheimer convinced General Leslie Groves to make Oppenheimer the scientific director of the Manhattan Project. Oppenheimer had the ability to persuade people, where Langan did not.

          Section 3.

          Psychologist Robert Sternberg calls the ability to persuade someone “practical intelligence.” It involves knowing what to say, how to say it, and when. It requires an ability to read situations. Individuals can have either practical or analytical intelligence, or in the case of Oppenheimer, both. To understand where one obtains practical intelligence, Gladwell refers to a study conducted by Annette Lareau.

          Lareau observed parenting strategies in both Black and white families from different socioeconomic strata. She found two distinct strategies: “concerted cultivation” and “accomplishment of natural growth.” Concerted cultivation, most common in middle-class and wealthier families, is defined by parents’ active promotion of their children’s talents and interests. Accomplishment of natural growth, most common in working-class or impoverished families, is defined by parents’ lack of interest or interaction in their children’s free time. Concerted cultivation, writes Gladwell, encourages children to seek opportunities for growth and to advocate for themselves. Accomplishment of natural growth leaves children unprepared to shape their environment for their own benefit. Concerted cultivation fosters an attitude better suited for success in the modern world.

          Section 4.

          Oppenheimer was raised by affluent parents who sent him to a progressive private school and took an active interest in his hobbies.

          • Affluent: Having an abundant supply of money or possessions of value.

          By contrast, Chris Langan’s brother Mark states that as children, they learned to resent authority. Mark, too, was unable to obtain financial aid, because he had no knowledge of how the system worked. If Chris Langan had been raised in a family that valued education, he probably would have had more success.

          Section 5.

          Once the Termites reached working adulthood, Terman grouped 730 of the males into three categories, based on their levels of success. The top 20 percent were upper-class professionals, while the bottom 20 percent had low-paying jobs or were unemployed. After analyzing the differences between the groups, Terman found that the bottom 20 percent came almost entirely from the lowest social and economic classes. What they lacked was “a community around them that prepared them properly for the world.”

          Section 6.

          Chris Langan lives on a horse farm in Missouri, where he still writes. He is happily married and continues to read physics and philosophy. While he has spent decades on his writing, almost none of it has ever been published. Langan admits he has not tried to contact publishers or found an agent—and does not plan to. Chris Langan did not have the support necessary to meet success. Gladwell points that no one ever makes it alone, regardless of if they are successful musicians, athletes, tech billionaires, or geniuses.

          Analysis: Chapter Four: The Trouble with Geniuses, Part 2

          Family background plays a crucial role in an individual’s success. While a genius like Chris Langan should thrive on a college campus, he drops out. Langan doesn’t struggle with academics, but with paperwork, procedures, and environment. Gladwell’s characterization of Langan almost makes him seem like two separate characters: a confident, genius game show contestant versus a child from a poor and troubled family. Langan may be a true outlier in the sense that he doesn’t seem to fit in academia or the working-class world.  Langan’s story is ironic. His brilliant mind should propel him to success. However, his story also perfectly proves Gladwell’s point that brainpower alone does not lead to success. The author delves deeper into the irony of Langan’s situation by comparing him to Robert Oppenheimer, who worked on the nuclear bomb during World War II. Like Langan, Oppenheimer possesses great intelligence. Unlike Langan, Oppenheimer has an understanding that allows him to navigate the world effectively. Oppenheimer knows how to combat challenges, where Langan gets bested by a financial aid problem and class schedule. Oppenheimer’s family background gave him the confidence to deal with authority while Langan’s upbringing created a distrust of authority. Without a family background that encourages success, intelligence is not enough.

          Contrast & Comparison

          Oppenheimer’s family background gave him the confidence to deal with authority while Langan’s upbringing created a distrust of authority.

          The power of persuasion is an important factor that drives success. Gladwell notes that the power of persuasion is practical intelligence. He contrasts practical intelligence with analytical ability, noting that just because a person is smart does not mean they have practical intelligence. These two types of knowledge are not necessarily coeval. He reinforces this point with a return to the comparison of Langan and Oppenheimer. Both men are exceedingly intelligent, but Langan lacks the social savvy of practical intelligence. Gladwell suggests that individuals gain practical intelligence skills from their families, discussing a study by sociologist Annette Lareau to prove his point. Children from wealthier families learn how to interact with society in a way that drives achievement. Successful people have the power of persuasion and can convince others to see things from their point of view.

          Success, then, depends on more than individual effort. Gladwell builds this argument by detailing the differences between Oppenheimer’s upbringing and Langan’s. Oppenheimer lived in an upper-class neighborhood with myriad advantages. He learned how to negotiate and stand up for himself. Langan’s family moved from place to place, struggling for jobs, money, food, and clothes, and Langan learned that he couldn’t rely on others. Gladwell's consideration of the Termites' success or struggles as adults supports his assertion that success is more than an individual effort; Gladwell states, “In the end, only one thing mattered: family background.” Terman’s findings and Gladwell’s conclusion do not mean that talented individuals from lower social and economic classes cannot have successful futures. To succeed, everyone needs help along the way, if not from family, then from a supportive community. Individuals do not achieve success solely on their own.

          Reference

          • “Outliers Chapter 4 Summary & Analysis.” SparkNotes, www.sparknotes.com/lit/outliers/section4/.
          + \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 00a29c60..e5d722ef 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1 +1 @@ -https://chodocs.cn/4042023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/getting-started2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/roadmap2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/file-naming-convention2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/rclone-for-r22023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/jp2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/chemistry2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/literature2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/vocabulary2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/markdown-it-katex/how-to-use2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/markdown-it-katex/support-function2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/markdown-it-katex/support-table2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/markdown-it-katex/tips2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/acknowledgement2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/appendix2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/assignments2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/author2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/aws-batch2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/aws-get-started2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/closing2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/cloud2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/docker-system2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/handson-bashoutter2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/handson-ec22023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/handson-jupyter2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/handson-qabot2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/handson-serverless2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/license2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/main2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/scientific-computing2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/serverless2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/development/aws/webserver2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/save/reading2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/chemistry/notes/12-52023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/chemistry/problems/02-202023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/chemistry/problems/03-02-12023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/chemistry/problems/03-02-22023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/chemistry/problems/03-02-32023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/literature/writing/methods-of-development2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/12023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/102023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/112023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/122023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/132023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/22023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/32023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/42023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/52023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/62023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/72023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/82023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/92023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/annotations2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/cutting2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/emit2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/errors2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/includes2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/logging2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/multi-file2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/queries2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/types2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/config/flags2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/config/reference2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/guide/custom-theme2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions2023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/javascript/notes/1/1-12023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/javascript/notes/1/1-22023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/save/reading/outliers/12023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/save/reading/outliers/22023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/save/reading/outliers/32023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/save/reading/outliers/42023-09-22T10:17:03.759Zdaily1.0https://chodocs.cn/academic/vocabulary/2023/02/2023-02-272023-09-22T10:17:03.759Zdaily1.0 \ No newline at end of file +https://chodocs.cn/4042023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/getting-started2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/roadmap2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/file-naming-convention2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/proxy4shell-terminal2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/rclone-for-r22023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/jp2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/chemistry2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/literature2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/vocabulary2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/markdown-it-katex/how-to-use2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/markdown-it-katex/support-function2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/markdown-it-katex/support-table2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/markdown-it-katex/tips2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/acknowledgement2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/appendix2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/assignments2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/author2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/aws-batch2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/aws-get-started2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/closing2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/cloud2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/docker-system2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/handson-bashoutter2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/handson-ec22023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/handson-jupyter2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/handson-qabot2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/handson-serverless2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/license2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/main2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/scientific-computing2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/serverless2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/development/aws/webserver2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/save/reading2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/chemistry/notes/12-52023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/chemistry/problems/02-202023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/chemistry/problems/03-02-12023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/chemistry/problems/03-02-22023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/chemistry/problems/03-02-32023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/literature/writing/methods-of-development2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/12023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/102023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/112023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/122023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/132023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/22023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/32023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/42023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/52023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/62023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/72023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/82023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/physics/ipho-formulas-jpn/92023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/annotations2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/cutting2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/emit2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/errors2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/includes2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/logging2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/multi-file2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/queries2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/api/types2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/config/flags2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/config/reference2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/guide/custom-theme2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions2023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/javascript/notes/1/1-12023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/javascript/notes/1/1-22023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/save/reading/outliers/12023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/save/reading/outliers/22023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/save/reading/outliers/32023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/save/reading/outliers/42023-11-03T22:54:19.134Zdaily1.0https://chodocs.cn/academic/vocabulary/2023/02/2023-02-272023-11-03T22:54:19.134Zdaily1.0 \ No newline at end of file